1, Thread, Runnable
- Runnable interface that defines the run() method.
- The Thread class implements the Runnable interface and overrides the run() method.
2, Callable
- Callable interface that defines the Call () method.
Executtor, AbstractExecutorService, ExecutorService, ThreadPoolExecutor
- The Executor interface, which defines the execute() method and accepts only Runnable objects.
- The ExecutorService interface defines the submit() method, which supports both Runnable and Callable.
- AbstractExecutorService class to implement the ExecutorService interface, rewrite the Submit () method.
- ThreadPoolExecutor class, AbstractExecutorService class, overriding execute().
Future, RunnableFuture, FutureTask
- The Future interface defines the get() method.
- The RunnableFuture interface, which inherits the Runalbe interface and the Future interface, is used to convert Callable to Runnable and return values.
- FutureTask class that implements the RunnableFuture interface and executes the Run () method.
5, for example,
- Create a new thread pool
ExecutorService executorService = new ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
Copy the code
- Construct the Callable/Runnable class and override the Call/Run method to implement the business logic of the task
new Callable<Object>(){
@Override
public Object call(a) throws Exception {
return "hello,ThreadPool"; }};Copy the code
- Call the thread pool’s Submit method to submit the task and get a Future object
Future<Object> future = executorService.submit(callable);
Copy the code
- ThreadPoolExecutor inherits the AbstractExecutorService class and does not write the Submit method, so the submit method of the ExecutorService is implemented in the AbstractExecutorService class
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
Copy the code
- Execute (ThreadPoolExecutor, ThreadPoolExecutor, ThreadPoolExecutor, ThreadPoolExecutor, ThreadPoolExecutor, ThreadPoolExecutor); Returns if the addWorker method executes successfully.
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return; c = ctl.get(); }}Copy the code
- The addWorker method is deleted as follows, in which the Runnable object is used as the parameter to build the Worker object, and the start method is executed after the thread in the Worker object is taken
private boolean addWorker(Runnable firstTask, boolean core) {
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
w = new Worker(firstTask);
final Thread t = w.thread;
if(t ! =null) {
if (workerAdded) {
t.start();
workerStarted = true; }}}return workerStarted;
}
Copy the code
- The Worker object is defined as follows, which implements the Runnable interface and inherits the AQS class. As you can see in the Worker constructor, a Runnable object is passed in and a new thread (not started) is created using the Runnable object as an argument. Calling the start method above actually starts the thread, and the start method will call the run method of the Worker object.
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable{
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
public void run(a) {
runWorker(this); }}Copy the code
- The run method of the Worker object actually calls the runWorker method, which in turn calls the run method. Question: Why take this step?
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
try {
task.run();
afterExecute(task, null); }}Copy the code
- The above run method actually executes the FutureTask class run method.
public class FutureTask<V> implements RunnableFuture<V> {
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable}}Copy the code
- Both Runnable and Callable objects are converted to Callable objects by executing the following run method
public void run(a) {
try {
Callable<V> c = callable;
if(c ! =null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
}
if(ran) set(result); }}}Copy the code
- See that the call method of the Callable object is executed in the run method, and the result returned is put into the outcome (CAS) through the set method.
protected void set(V v) {
if (STATE.compareAndSet(this, NEW, COMPLETING)) {
outcome = v;
STATE.setRelease(this, NORMAL); // final statefinishCompletion(); }}Copy the code
- Call the get method to get the result of the task execution
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Copy the code
- The get method calls the Report method
public V get(a) throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false.0L);
return report(s);
}
Copy the code
- The report method returns the outcome value to the output
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
Copy the code