Java uses the thread pool to perform a number of tasks

When performing a series of tasks with asynchronous IO operations (such as downloading files), and unrelated, multi-threading can greatly improve operational efficiency. Thread pool contains a series of threads, and can manage these threads. For example: create a thread, the thread destroyed and so on. This article describes how to perform tasks using Java threads in the pool.

1 Task Type

Before using the thread pool to perform tasks, we figure out what tasks can be called from the thread pool. Task returns a value according to whether the task can be divided into two types, namely, to achieve the Runnable task class (No parameter returns no value) class interface and implementation Callable task (no return value parameters). When playing the corresponding code is selected according to the type of job requirements.

1.1 implement Runnable class

Multi-threaded task type, the natural first thought is to achieve  Runnable  interface class, Runnable interface provides an abstract method run, this method has no parameters, no return value. E.g:

Runnable task = new Runnable() {
    @Override
    public void run() {
        System.out.println("Execute task.");
    }
};

Or Java 8 or later simpler wording:

Runnable task = ()->{
    System.out.println("Execute task.");
};

1.2 implement Callable interface class

Callable at the same Runnable only one abstract method, but the abstract method returns a value. The need to develop the type of return value at the time of implementation of this interface. E.g:

Callable<String> callableTask = ()-> "finished";

2 types of thread pool

java.util.concurrent.Executors provides a series of static methods to create a variety of thread pool. The following example of a thread pool and some of the main characteristics, other characteristics of the thread pool is not exemplified those derived by the following.

A fixed number of threads in the thread pool 2.1 Fixed Thread Pool

As the name implies, this type of thread pool threads number is fixed. If the number of threads to n, then the thread pool at any time at most n threads running. When the thread pool to run in a saturated state, the thread pool task and then further submissions will be placed in the execution queue. If the thread pool is in the unsaturated state, the thread pool will exist until the shutdown ExecuteService method is called, the thread pool will be cleared.

// Create a number of threads in the thread pool 5. 
ExecutorService executorService = Executors.newFixedThreadPool (5);

2.2 can be cached thread pool Cached Thread Pool

This type of thread pool threads initial size is 0, with the pool to continue to submit the task, if there is no idle thread pool thread (0 threads also means no idle threads), a new thread is created to ensure that no task waiting; if there is idle thread, the thread performs multiplexing idle task. Thread is idle for 60 seconds only cached thread pool idle time reaches 60s thread will be closed and removed from the thread pool. In the process a large number of short-lived: when (the official statement short-lived) asynchronous task can have a significant provider performance.

// create a cached thread pool 
ExecutorService executorService = Executors.newCachedThreadPool ();

2.3 single-threaded Pool

This may not be called the thread pool, because it is inside the thread is always only one, and only one from beginning to end (Why say this, because you want to and  Executors.newFixedThreadPool (1)  distinguish), they still call it " the pool of single-threaded. " You can rest in the past a single thread pool add tasks, but each time only execute one, and the task is executed sequentially. If the previous task appeared abnormal, the current thread will be destroyed, but a new thread will be created to perform the latter task. These and a number of threads that only one thread Fixed Thread Pool same. The only difference is that both,  Executors.newFixedThreadPool (1)  can modify the number of threads in it at runtime, but  Executors.newSingleThreadExecutor ()  can only ever have a thread. As for the "why", I am going to write a blog dedicated to analysis by source code.

// create a single thread pool 
ExecutorService executorService = Executors.newSingleThreadExecutor ();

 2.4 Work stealing thread pool

Clawed source code, you will find work stealing thread pool is essentially  ForkJoinPool  , this type of thread pool full advantage of multi-core CPU processing tasks, for handling tasks consume CPU resources and more. It's not a fixed number of threads, maintaining multiple task queue, the queue when a task is completed, the corresponding thread steal task execution queue from other tasks, it also means the beginning of the execution order of tasks and the order and submit the same . If there is a higher demand, the thread pool can get directly through ForkJoinPool.

// create a work-stealing thread pool, use the machine's CPU core number equal to the number of nuclear CPU 
ExecutorService ExecutorService = Executors.newWorkStealingPool ();

// create a work-stealing thread pool, use the CPU 3 nuclei are calculated, the work can not be set to steal the thread pool threads 
ExecutorService executorService2 = Executors.newWorkStealingPool (3);

2.5 Scheduled Tasks thread pool

Scheduled Tasks thread pool can perform certain tasks according to plan, for example: periodically perform a task.

// get a scheduled task thread pool size 2 
ScheduledExecutorService ScheduledExecutorService = Executors.newScheduledThreadPool (2 );
 
// add a thread information Print scheduled task, the task is executed after 3 seconds scheduledExecutorService.schedule (() -> {System .out.println (Thread.currentThread ());}, 3 , TimeUnit.SECONDS);
// add a thread information Print scheduled task, the task for the first time executed after two seconds, after performing once every 5 seconds. If the task execution time exceeds 5 seconds, the next time will be immediately after the previous execution completion scheduledExecutorService.scheduleAtFixedRate (() -> {System.out.println (Thread.currentThread ());}, 2,. 5 , TimeUnit.SECONDS);
// add a thread information Print scheduled task, the task for the first time executed after two seconds, and then the next time every five seconds after the task execution. scheduledExecutorService.scheduleWithFixedDelay (() -> {System.out.println (Thread.currentThread ());}, 2,. 5 , TimeUnit.SECONDS);
//Clear idle state-by-thread scheduledExecutorService.shutdown ();
// blocked, the code will not go down before the thread pool is closed tune scheduledExecutorService.awaitTermination (Long.MAX_VALUE, TimeUnit.SECONDS);

 3 Use the thread pool to perform tasks

As mentioned earlier, the type of task types are divided into the return value and no return value, call here is also divided into the value of calls and return calls no return value.

3.1 No return call value tasks

If the value is not returned to the calling task can execute or submit method, both on essentially the same in this case. In order to return to duty tasks call to maintain unity, submit recommended method.

// create a thread pool 
ExecutorService ExecutorService = Executors.newFixedThreadPool (3 );

// submit a task no return value (implements Runnable interface) 
ExecutorService.submit (() -> System.out.println ( "the Hello"));

executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);

If there is a set of tasks, you can submit one by one.

// create a thread pool 
ExecutorService ExecutorService = Executors.newFixedThreadPool (3 );
List<Runnable> tasks = Arrays.asList(
        ()->System.out.println("Hello"),
        ()->System.out.println("World"));

// individually submit task 
tasks.forEach (executorService :: submit);

executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);

3.2 returns a value tasks call

There are value-returning task need to implement Callable Interface, when implemented in a generic return type specified location. When you call the submit method returns a Future object, get through the Future method () can get the return value. It should be noted that, when you call get () code block until the task is completed, there is a return value.

ExecutorService executorService = Executors.newFixedThreadPool(2);
Future<String> future = executorService.submit(()->"Hello");
System.out.println(future.isDone());//false
String value = future.get();
System.out.println(future.isDone());//true
System.out.println(value);//Hello

If you want to submit a number of tasks, ExecutorService in addition can submit one by one, you can also call invokeAll submit a one-time, invokeAll internal implementation is actually using a cycle-by-submit the job. InvokeAll value returned is a Future List.

ExecutorService executorService = Executors.newFixedThreadPool(2);
List<Callable<String>> tasks = Arrays.asList(()->"Hello", ()->"World");
List<Future<String>> futures = executorService.invokeAll(tasks);

invokeAny method is also useful thread pool to perform a number of implements Callable task, and then returns the value end of the first to perform a task, other tasks will not be properly canceled there will be no exception. The following code is not output "Hello"

ExecutorService executorService = Executors.newFixedThreadPool(2);
List<Callable<String>> tasks = Arrays.asList(
        () -> {
            Thread.sleep(500L);
            System.out.println("Hello");
            return "Hello";
        }, () -> {
            System.out.println("World");
            return "World";
        });
String s = executorService.invokeAny(tasks);
System.out.println(s);//World

Output:

World
World

Further, it provides a method was found when viewing source ExecutorService  <T> Future <T> Submit (Runnable Task, Result T);  , this method may be submitted through a task implements Runnable interface, and returns a value, and no return value of the method when run Runnable interface. The return value is that it come from? In fact, the problem is that an argument behind the submit method, this parameter value is returned. After calling submit method, there is a pass operation, and then returns the result parameter directly.

ExecutorService executorService = Executors.newFixedThreadPool(1);
Future<String> future = executorService.submit(() -> System.out.println("Hello"), "World");
System.out.println(future.get());//输出:World

4 Summary

When using multi-threaded processing tasks, you should choose the right type of task and thread pool type according to the situation. If no return value, may be employed to achieve the task Callable or Runnable interface; if the return value, should be used to achieve Callable interface task, the return value of the get method takes into Future. The selection of the thread pool, if only by a thread, or with a single thread pool thread pool capacity of fixed capacity 1; handle large short-live task is to use cached thread pool; there are plans to perform some or cycle task, you can use the Scheduled tasks thread pool; if the task needs to consume a lot of CPU resources, applications, work-stealing thread pool.

Guess you like

Origin www.cnblogs.com/robothy/p/12101491.html