ExecutorService

There are two implementations of the ExecutorService interface in the Java API, so these two are the concrete implementation classes of the Java thread pool:

1. ThreadPoolExecutor
2. ScheduledThreadPoolExecutor

ExecutorService also inherits the Executorinterface (note the distinction between the Executor interface and the Executors factory class), this interface has only one execute()method, and finally we look at the entire inheritance tree

è¿ ™ é ‡ Œå † ™ å ›¾ç ‰ ‡ æ è¿ °

Creation of ExecutorService

Java provides us with one Executors工厂类, which can help us easily create various types of ExecutorService thread pools. Executors can create the following four types of thread pools:

newCachedThreadPool: Create a cacheable thread pool. If the length of the thread pool exceeds the processing requirement, idle threads can be flexibly recycled. If there is no recycling, new threads will be created.

newFixedThreadPool: Create a fixed-length thread pool, which can control the maximum number of concurrent threads. Exceeded threads will wait in the queue.

newScheduledThreadPool: Create a fixed-length thread pool to support scheduled and periodic task execution.

newSingleThreadExecutor: Creates a single-threaded thread pool that only uses a single worker thread to execute tasks, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority).

Executors is just a factory class, and all its methods return instances ThreadPoolExecutorof ScheduledThreadPoolExecutorthese two classes.

Use of ExecutorService

ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(new Runnable() {
public void run() {
    System.out.println("Asynchronous task");
}
});

executorService.shutdown();

ExecutorService execution

ExecutorService has the following execution methods:

- execute(Runnable)
- submit(Runnable)
- submit(Callable)
- invokeAny(...)
- invokeAll(...)

execute(Runnable)

This method receives a Runnable instance and executes it asynchronously, see the following example:

ExecutorService executorService = Executors.newSingleThreadExecutor();

executorService.execute(new Runnable() {
public void run() {
    System.out.println("Asynchronous task");
}
});

executorService.shutdown();

The problem with this method is that there is no way to know the execution result of the task. If we want to get the execution result of the task, we can pass in an instance of Callable.

submit(Runnable)

submit(Runnable)The execute(Runnable)difference is that the former can return a Future object. Through the returned Future object, we can check whether the submitted task is completed. Please see the following execution example:

Future future = executorService.submit(new Runnable() {
public void run() {
    System.out.println("Asynchronous task");
}
});

future.get();  //returns null if the task has finished correctly.

If the task execution is complete, the future.get()method returns a null. Note that the future.get() method will block.

submit(Callable)

submit(Callable)Similarly , submit(Runnable)a Future object is also returned, but in addition, submit(Callable) receives an implementation of Callable. The call()method in the Callable interface has a return value that can return the execution result of the task, while the Runnable interface has a return value. run()Method yes void, no return value. See the example below:

Future future = executorService.submit(new Callable(){
public Object call() throws Exception {
    System.out.println("Asynchronous Callable");
    return "Callable Result";
}
});

System.out.println("future.get() = " + future.get());

If the task execution is completed, the future.get() method will return the execution result of the Callable task. Note that the future.get() method will block.

invokeAny(…)

invokeAny(...)The method receives a collection of Callables. Executing this method will not return a Future, but will return the execution result of one of all Callable tasks. This method also cannot guarantee which task execution result is returned, it is one of them anyway. See the example below:

ExecutorService executorService = Executors.newSingleThreadExecutor();

Set<Callable<String>> callables = new HashSet<Callable<String>>();

callables.add(new Callable<String>() {
public String call() throws Exception {
    return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
    return "Task 2";
}
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
    return "Task 3";
}
});

String result = executorService.invokeAny(callables);
System.out.println("result = " + result);
executorService.shutdown();

invokeAll(…)

invokeAll(...)Similar  invokeAny(...)to receiving a Callable collection, but the former will return a Future List after execution, which corresponds to the Future object after each Callable task is executed. The following example

ExecutorService executorService = Executors.newSingleThreadExecutor();

Set<Callable<String>> callables = new HashSet<Callable<String>>();

callables.add(new Callable<String>() {
public String call() throws Exception {
    return "Task 1";
}
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
    return "Task 2";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
    return "Task 3";
}
});

List<Future<String>> futures = executorService.invokeAll(callables);

for(Future<String> future : futures){
System.out.println("future.get = " + future.get());
}

executorService.shutdown();

ExecutorService shutdown

When we finish using ExecutorService, we should close it, otherwise the threads in it will always be running.

For example, if the application is started through the main() method, after this main() exits, if the ExecutorService in the application is not closed, the application will continue to run. This happens because the threads running in the ExecutorService prevent the JVM from shutting down.

If we want to shut down the thread executing in the ExecutorService, we can call the ExecutorService.shutdown()method. After calling the shutdown() method, the ExecutorService will not shut down immediately, but it will no longer receive new tasks, and will not shut down until all current threads are executed, and all tasks submitted before shutdown() execution will be executed.

If we want to shut down the ExecutorService immediately, we can call the ExecutorService.shutdownNow()method. This action will skip all executing tasks and tasks that are submitted and not yet executed. But it does not make any guarantees about the tasks being executed, it is possible that they will all stop, or they may complete.

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325466934&siteId=291194637