Consider having such a liftoff class:
/** * Class Liftoff.java Implementation Description: Displays the countdown before launch * */public class LiftOff implements Runnable {public LiftOff () { taskcount++;//count self-increment } private int countdown = 3; Countdown number private static int taskcount = 0; private int id = taskcount; @Override public Void Run () {while (Countdown >= 0) { System.out.println ("thread number" + ID + "--Countdown" + COUNTD Own); countdown--; Thread.yield ();}}}
And a launch main thread:
public class Launch {public static void Main (string[] args) { LiftOff LiftOff = new LiftOff (); Thread t = new thread (LIFTOFF); T.start (); SYSTEM.OUT.PRINTLN ("Launch!");}
Our intention is to show the countdown first and then show "Launch!" ", the result of the operation is
Launch! Thread number 0--Countdown 3 thread number 0--Countdown 2 thread number 0--Countdown 1 thread number 0--Countdown 0
Because the main () function is also a thread, the ability of the program to get the correct results depends on the relative execution speed of the thread, which we cannot control. If you want to make the liftoff thread execute before proceeding with the main thread, it is easy to think of a poll:
Press CTRL + C to copy the code<textarea></textarea>Press CTRL + C to copy the code
We added the Isover variable, set the Isover to true at the end of the countdown, and we constantly judge the Isover state in the main function, and we can tell if the liftoff thread is finished:
Press CTRL + C to copy the code<textarea></textarea>Press CTRL + C to copy the code
Execute main (), Output:
Thread number 0--Countdown 3 thread number 0--Countdown 2 thread number 0--Countdown 1 thread number 0--Countdown 0 launch!
This solution is feasible, it will give the correct results in the correct order, but the query is not only wasteful performance, and may be busy with the main line ride too check the completion of the work, so that the specific work thread is not set aside time, the better way is to use the callback (callback) , when the thread completes, it calls its creator in turn, telling it that the work is over:
public class LiftOff implements Runnable { private Launch Launch; Public LiftOff (Launch Launch) { taskcount++;//count self-increment this.launch = Launch; } private int countdown = 3; Countdown number private static int taskcount = 0; private int id = taskcount; @Override public Void Run () {while (Countdown >= 0) { System.out.println ("thread number" + ID + "--Countdown" + COUNTD Own); countdown--; if (Countdown < 0) { launch.callback (); } Thread.yield ();}}}
Main thread Code:
public class Launch {public void CallBack () { System.out.println ("Launch!"); } public static void Main (string[] args) { Launch Launch = new Launch (); LiftOff LiftOff = new LiftOff (launch); Thread t = new thread (LIFTOFF); T.start (); }}
Operation Result:
Thread number 0--Countdown 3 thread number 0--Countdown 2 thread number 0--Countdown 1 thread number 0--Countdown 0 launch!
The first advantage of the callback mechanism, compared to the polling mechanism, is that it does not waste so much CPU performance, but the more important advantage is that the callback is more flexible and can handle more complex situations involving more threads, objects, and classes.
For example, if more than one object is interested in the calculation of a thread, the thread can hold a list of objects to be recalled, and the objects interested in the results can be registered by calling the method to add themselves to the object list. When the thread finishes processing, the thread will call back those objects that are interested in the results of the calculation. We can define a new interface, all of which will implement this new interface, and the new interface declares the callback method. This mechanism has a more general name: The Observer (Observer) design pattern.
Callable
JAVA5 introduces a new approach to multithreaded programming that makes it easier to handle callbacks. The task can implement the callable interface instead of the Runnable interface, submit the task through executor and get a future, and then request the result of the task to the next:
public class LiftOff implements callable<string> {public LiftOff () { taskcount++;//count self-increment } private int countdown = 3; Countdown number private static int taskcount = 0; private int id = taskcount; @Override public String call () throws Exception {while (Countdown >= 0) { System.out.println ("Thread number" + ID + "--Countdown" + countdown); countdown--; } Return "thread number" + ID + "--end"; }}
Main function:
public class Launch {public static void Main (string[] args) { Executorservice executor = Executors.newcachedthre Adpool (); future<string> future = Executor.submit (New LiftOff ()); try { String s = future.get (); System.out.println (s); } catch (Interruptedexception | Executionexception e) { e.printstacktrace (); } SYSTEM.OUT.PRINTLN ("Launch! "); }}
Operation Result:
Thread number 0--Countdown 3 thread number 0--Countdown 2 thread number 0--Countdown 1 thread number 0--Countdown 0 thread number 0--end launch!
Easy to submit multiple tasks with executor:
public class Launch {public static void Main (string[] args) { Executorservice executor = Executors.newcachedthre Adpool (); list<future<string>> results = new arraylist<> (); Multi-threaded execution of three tasks for (int i = 0; i < 3; i++) { future<string> = executor.submit (New LiftOff ()); Results.add (future); } Gets the threading result for (future<string> result:results) { try { String s = result.get (); System.out.println (s); } catch (Interruptedexception | Executionexception e) { e.printstacktrace (); } } Continue the main thread process System.out.println ("Launch! "); }}
Results:
Thread number 0--Countdown 3 thread number 0--Countdown 2 thread number 0--Countdown 1 thread number 0--Countdown 0 thread number 2--Countdown 3 thread number 2--Countdown 2 thread number 3 thread number 2 thread count 1 thread number 0 thread number Thread number 2--Countdown 0 thread number 0--end thread number The end thread number 2--end launch!
As you can see, the Get () method of the future, if the result of the thread is ready, will get the result immediately, and if it is not ready, the polling thread will block until the result is ready.
Benefits
Using callable, we can create many different threads and get the answers we want in the order we need them. In addition, if there is a time-consuming calculation problem, we can also divide the computational amount into multiple threads to process, and finally summarize the processing results of each thread, thus saving time.
How to return information from a thread-polling, callback, callable