First, say thread,runnable and callable
multithreaded programs are written in order to achieve multitasking concurrent execution, which enables better interaction with the user. There are generally three ways to thread,runnable,callable.
The difference between runnable and callable is:
(1) The method prescribed by callable is call (), and the method specified by runnable is run ().
(2) Callable can return a value after a task is executed, and Runnable's task is not to return a worthwhile
(3) Call method can throw an exception, the Run method can not
(4) Run the callable task to get a future object that represents the result of an asynchronous calculation. It provides a way to check whether the calculation is complete, to wait for the completion of the calculation, and to retrieve the results of the calculation. The future object enables you to understand task execution, cancel the execution of a task, and get execution results.
1. Create thread threads by implementing the Runnable interface:
Step 1: Create a class that implements the Runnable interface:
class Implements Runnable { publicvoid Run () { //dosomething-Here }
}
Step 2: Create a Class object:
Runnable onerunnable = newsomerunnable ();
Step 3: Create a Thread object from runnable:
Thread Onethread = Newthread (onerunnable);
Step 4: Start the thread:
Onethread.start ();
At this point, a thread is created.
Note: The execution process of a thread is simple, and when code Onethread.start () is executed, the Voidrun () in the Onerunnable object is executed;
When the method executes, the thread dies.
2, similar to Method 1, by implementing the callable interface to create thread threads: where the Callable interface (and only one method) is defined as follows:
public interfacecallable<v>{ throws Exception;}
Step 1: Create a class that implements the callable interface somecallable<integer> (slightly);
Step 2: Create a Class object:
callable<integer> onecallable = newsomecallable<integer> ();
Step 3: Create a Futuretask<integer> object from callable<integer>:
futuretask<integer> OneTask = newfuturetask<integer> (onecallable);
Note:futuretask<integer> is a wrapper that is created by accepting Callable<integer>, which implements both the future and the Runnable interface.
Step 4: Create a Thread object from futuretask<integer>:
Thread onethread = new Thread (onetask);
Step 5: Start the thread:
Onethread.start ();
At this point, a thread is created.
3. Create a thread by inheriting the thread class:
Step 1: Define a subclass that inherits the thread class:
class Sometheadextends thraad{ publicvoid Run () { //do somethinghere }}
Step 2: Construct an object for the subclass:
Somethread onethread = new Somethread ();
Step 3: Start the thread:
Onethread.start ();
At this point, a thread is created.
Note: This method of creating threads is not good enough, mainly because it involves a running mechanism problem that affects program performance.
4. Create threads by line pool:
Step 1: Create the thread pool:
Executorservice pool =executors.newcachedthreadpool ();
Step 2: Submit the task to the Executorservice object by Runnable object or callable object:
Future<integer>submit (callable<integer> Task);
Note: The future is an interface, which is defined as follows:
public interfacefuture<t>{ throws ...; V get (longthrows...; void cancle (boolean mayinterrupt); boolean iscancelled (); boolean isDone ();}
At this point, a thread is created.
Note: The thread pool needs to call the shutdown () method to close the threads.
5. Using the event allocation thread to directly use the original thread in the program:
How to use:
Call the static method of the EventQueue class directly Invokelater ():
Eventqueue.invokelater (onerunnable);
Note: Call Eventqueue.invokelater (onerunnable); the run () method in the Onerunnable object is executed directly.
Second, to say the future and Futuretask
The future is an interface, and Futuretask is its common implementation class. Represents an asynchronous task, which is a future result given by a task that has not yet been completed. They are located under the Java.util.concurrent package and can be canceled for specific runnable or callable task execution results, and the query is completed and results obtained. If necessary, the result of the execution can be obtained through the Get method, which blocks until the task returns the result.
The future interface is defined as follows:
public Interfacefuture<v> { boolean cancel (booleanmayinterruptifrunning); Boolean iscancelled (); boolean isDone (); throws interruptedexception,executionexception; V get (longthrows interruptedexception,executionexception, timeoutexception;}
5 of these methods function as follows:
The Cancel () method is used to cancel the task and returns true if the Cancel task succeeds, or False if the cancel task fails.
The IsCancelled () method indicates whether the task was canceled successfully and returns true if the task was canceled successfully before it was properly completed.
The IsDone () method indicates whether the task has completed and returns true if the task completes;
The Get () method is used to get the result of the execution, this method will be blocked, will wait until the task is completed before returning;
Get (longtimeout, Timeunit unit) is used to get the execution result, and if the result is not obtained within the specified time, NULL is returned directly.
This means that the future offers three functions:
1) Determine whether the task is completed;
2) ability to interrupt tasks;
3) Ability to get task execution results.
Because the future is just an interface, it is not directly used to create objects to use, look at Futuretask in detail.
Let's take a look at the implementation of Futuretask:
Public Classfuturetask<v> implements Runnablefuture<v>
The Futuretask class implements the Runnablefuture interface, and we look at the implementation of the Runnablefuture interface:
Public extends Runnable, future<v> { void run ();}
It can be seen that runnablefuture inherits the Runnable interface and the future interface, and Futuretask implements the Runnablefuture interface. So it can be executed as runnable by thread, and can get callable return value as future.
The Futuretask provides 2 constructors:
Publicfuturetask (callable<v> callable) {}
Publicfuturetask (Runnable Runnable, V result) {}
In fact, Futuretask is a unique implementation class for the future interface. Designed to compensate for the lack of thread, it allows the programmer to know exactly when the thread is executing and gets the results that are returned when the thread finishes executing (if necessary).
Third, then said executor, executors, Executorservice, Threadpoolexecutor, Scheduledthreadpoolexecutor and Completionservice and Executorcompletionservice.
These represent task actuators or services related to asynchronous tasks, for more information about them, see: http://man.ddvip.com/program/java_api_zh/index.html?java/util/concurrent/Executor.html.
Where the executor interface is used to perform the objects of the submitted Runnable task. This interface provides a way to separate task submissions from the mechanics of how each task will run, including details, schedules, and so on, that are used by threads. Typically, you use Executor instead of explicitly creating threads. The Executorservice implements the executor interface, which is a more extensive interface. The Threadpoolexecutor class provides an extensible thread pool implementation. The Executors class provides a convenient factory approach for these Executor.
where Scheduledthreadpoolexecutor (STPE) inherits from Threadpoolexecutor, realizes the Executor,executorservice, The Scheduledexecutorservice interface, which is the top priority in the thread pool class, features a wide range of functions and is popular. This magical class will be described in more detail later.
The Completionservice interface is used to separate the production of new asynchronous tasks from the results of using completed tasks. The task that the producer submit to perform. The consumer take the completed tasks and process their results in the order in which they were completed. For example, Completionservice can be used to manage asynchronous IO, the task of performing a read operation is committed as part of a program or system, and then, when the read operation is completed, other actions are performed in different parts of the program, and the Order of operations may differ from the order in which they were requested.
Typically, Completionservice relies on a single executor to actually perform tasks, in which case Completionservice only manages an internal completion queue. The Executorcompletionservice class provides an implementation of this method.
U detailed scheduledthreadpoolexecutor:
Since jdk1.5, Java has started to provide scheduledthreadpoolexecutor classes to support the scheduling of periodic tasks, which need to rely on Timer/timertask or other third-party tools to do so. But the timer has a lot of flaws, such as a timer is single-threaded mode, scheduling multiple periodic tasks, if a task takes a long time to affect the scheduling of other tasks, if a task is an exception and not caught can cause the unique thread to die and all tasks will no longer be dispatched. Scheduledthreadpoolexecutor solves many of the shortcomings of the timer.
Let's take a look at the implementation model of Scheduledthreadpoolexecutor, which uses the function of the thread pool by inheriting threadpoolexecutor to do a few things:
A delayedworkqueue is set for the thread pool that has both priorityqueue (the element with the highest priority placed on the team head) and Delayqueue (if the Getdelay return value of the first element in the queue is greater than 0, The function that the take call will block)
Encapsulating incoming tasks into Scheduledfuturetask, this class has two features, Implements the java.lang.Comparable and java.util.concurrent.Delayed interfaces, which means that there are two important methods in it: CompareTo and Getdelay. The Scheduledfuturetask stores the time it takes for the task to be next scheduled (using the relative time based on the System#nanotime implementation, and will not change due to changes in system time, such as 10 seconds from the next execution, does not become 4 seconds after the system time is adjusted to 6 seconds). The Getdelay method is to return the difference between the current time (at this point in the run Getdelay) from the next call, and the CompareTo to compare the precedence of the two tasks, which is shorter than the next scheduled interval. So, when a task is dropped into the delayedworkqueue mentioned above, because it has the function of Delayqueue (Delayqueue's internal use priorityqueue), the new task will be sorted with the task that already exists in the queue, Tasks that are shorter than the next scheduled interval are in front, meaning that the queue is not FIFO, and if there are no elements at the time of the call to the Delayedworkqueue take method, If there is an element and the first element's Getdelay return value is greater than 0 (as previously stated, the first element's getdelay will not be greater than the Getdelay return value of the subsequent element), and it will always block.
Scheduledfuturetask provides a run implementation that the thread pool executes is the Run method. Look at the source of the run (the code in this article is taken from the HOTSPOT1.5.0_22,JDK later version of the code may have been different, such as jdk1.7 in the use of their own implementation of the Delayedworkqueue, and no longer use priorityqueue as storage, but from the outside to see their behavior is the same, so it does not affect the Scheduledthreadpoolexecutor scheduling mechanism of understanding):
Public void Run () { if (Isperiodic ()) { runperiodic (); } Else { scheduledfuturetask. Super. Run ();} }
If it is not a recurring task to execute the task directly (that is, the else part), this is mainly used to implement Scheduledthreadpoolexecutor#schedule (callablecallable, long delay, timeunit Unit) and Scheduledthreadpoolexecutor#schedule (Runnablecommand, long delay, timeunit unit), followed by their implementation, which focuses on how the periodic task is executed. The recurring task executes the Runperiodic () and looks at its implementation:
PrivateVoidrunperiodic () {BooleanOK =scheduledfuturetask.Super. Runandreset ();BooleanDown = IsShutDown ();//Reschedule if not cancelled and Notshutdown or policy allowsif(OK && (!down | | (Getcontinueexistingperiodictasksaftershutdownpolicy () &&!isterminating ()))) {Longp = period;if(P > 0) {time + = p; }Else{time = Triggertime (-p); } scheduledthreadpoolexecutor.Super. Getqueue (). Add ( This); }//This might has been the final executeddelayed//task. Wake up threads to check.Else if(down) {interruptidleworkers (); }}
As you can see here, the task itself (ScheduledFutureTask.super.runAndReset) is executed first, and the call has a return value to see its implementation:
Protectedboolean Runandreset () { return sync.innerrunandreset ();}
Follow up to see the Innerrunandreset ():
Boolean Innerrunandreset () { if (!compareandsetstate (0, RUNNING)) { returnfalse; } try { runner = Thread.CurrentThread (); //don ' t set result null; return compareandsetstate (RUNNING, 0); Catch (Throwable ex) { innersetexception (ex); returnfalse; }}
It can be found that the third return is to be followed, that is, if the task execution has an exception, it will catch and return false.
Keep looking at the Runperiodic () method, if inside, if the return value of the task execution is true and the thread pool is still running in the If block operation, if the thread pool is closed, do the else if operation. In other words, if the exception of the previous task execution returns false, then the code in the IF and else if will not execute, what is the effect? Let's see what happens in If.
If the code is very simple, divided into two parts, one is to calculate the next interval of the task scheduling, and the second is to put the task back into the queue. Back to the situation where the exception occurred, if the task has just been an exception, the task will not be put back into the queue, in other words, this task is no longer scheduled! However, this does not affect the scheduling of other periodic tasks.
In summary, you can see that the model that Scheduledthreadpoolexecutor performs a recurring task is to schedule a task, calculate and set the next interval for the task, and put the task back in the queue for execution by the thread pool. The queues here play a big role, and there are some features: The task is always at the head of the team at the next scheduled interval, and the task of the first team is not able to get the task from the Take () method of the queue if it is more than 0 from the next scheduled time interval.
Next look at Scheduledthreadpoolexecutor#schedule (callablecallable, long delay, timeunit unit) and Scheduledthreadpoolexecutor #schedule (Runnablecommand, long delay, timeunit unit) The implementation of these two non-cyclical tasks, first look at their source code:
publicscheduledfuture<?> Schedule (Runnable command,LongDelay, Timeunit unit) {if(Command = =NULL|| Unit = =NULL){Throw NewNullPointerException ();} scheduledfuturetask<?> T =newscheduledfuturetask<boolean> (command,NULL, Triggertime (delay, unit));d Elayedexecute (t);returnt;} Public<V>ScheduledFuture<V> Schedule (callable<v> callable,LongDelay,timeunit unit) {if(Callable = =NULL|| Unit = =NULL){Throw NewNullPointerException ();} Scheduledfuturetask<v> T =newscheduledfuturetask<v> (callable, Triggertime (delay, unit));d Elayedexecute (t);returnt;}PrivateVoiddelayedexecute (Runnable command) {if(IsShutDown ()) {Reject (command);return;}//Prestart a thread if necessary. Wecannot Prestart It//running the task because the task (probably) shouldn ' t be//Run yet, so thread would just idle untildelay elapses.if(Getpoolsize () < Getcorepoolsize ()) {Prestartcorethread ();}Super. Getqueue (). Add (command);}
The implementation is also simple, when creating scheduledthreadpoolexecutor internal tasks (that is, scheduledfuturetask), the scheduling interval is calculated and set, if the current number of threads is less than the number of core threads set, Start a thread (it may be that the thread pool has just started and there are no threads in it, or it may be that the threads inside are dead when the task is executed). If threads in the thread pool are hung up without calling these schedule methods who is going to replenish the hung thread? Do not worry, the thread pool itself will be processed) to listen to tasks in the queue, and then put the task in the queue, the task execution interval is not greater than 0, the thread can get this task and execute.
The entry of the recurring task (Scheduledthreadpoolexecutor#scheduleatfixedrate (Runnablecommand, long initialdelay, long period, timeunit Unit) and Scheduledthreadpoolexecutor#schedulewithfixeddelay (Runnablecommand, long initialdelay, long delay, TimeUnit Unit) is similar to non-cyclical tasks, where they are handled in a different way than the Scheduledfuturetask#run () mentioned earlier.
Concurrent Programming and Task modeling