Home > Net >  Permanent Java
Permanent Java

Time:09-21

Multithreading, the thread pool open right way

An overview of the

Can be considered to be operating system thread scheduling, the minimum program execution sequence, generally as part of the process, multiple threads can be Shared in the same process the process of resources (such as memory, etc.), the JVM thread with the kernel lightweight process there is a one-to-one mapping relationship, so it is very precious, threads in the JVM

General multi-threading implementation in engineering is based on the thread pool, because compared himself to create threads, multithreading has the following advantages

Threads are scarce resources, the use of thread pool can reduce the number of creating and destroying threads, each worker thread can be repeated use,

Can be based on the system capacity, adjust the work the number of threads in thread pool, prevent because consumes too much memory to crash the server,

What's the main problem Executors

See alibaba development manual concurrent programming on this one: thread pool Executors are not allowed to be used to create, but through the way of ThreadPoolExecutor,



The defect of Executors why

1. The working principle of the thread pool



When a task through the execute (Runnable) method to add to the thread pool:

If the quantity of the thread pool is less than corePoolSize, even if the idle threads in the pool, and to create a new thread to handle the added tasks,

If the thread pool is equal to the number of corePoolSize, but buffer queue workQueue under, so the task is placed into a buffer queue,

If the quantity of the thread pool is greater than the corePoolSize and buffer queue workQueue is full, and the quantity is less than the thread pool maximumPoolSize, building a new thread to handle the added tasks,

By handler specified strategies to deal with this task, namely: the priority of the processing tasks for: core thread corePoolSize workQueue task queue, maximum thread maximumPoolSize, if all have full, USES a handler to handle the rejected tasks,

While the number of threads in the pool is greater than the corePoolSize, if a thread free time more than keepAliveTime, thread will be terminated, in this way, the thread pool can dynamically adjust the number of threads in the pool,

2.
newFixedThreadPool analysis

In Java BlockingQueue there are two main implementation, ArrayBlockingQueue and LinkedBlockingQueue,

ArrayBlockingQueue is an array is used to implement a bounded blocking queue, you must set up capacity,

LinkedBlockingQueue is a linked list is used to implement a bounded blocking queue, capacity can choose to set, is not set, will be a blocking queue without borders, a maximum length of the Integer. MAX_VALUE,

The problem here is in: it is not set, it will be a blocking queue without borders, a maximum length of the Integer. MAX_VALUE, that is to say, if we do not set LinkedBlockingQueue capacity, its default capacity will be an Integer. MAX_VALUE,

And create newFixedThreadPool LinkedBlockingQueue, does not specify capacity, at this point, the LinkedBlockingQueue is a borderless queue, for a borderless queue can be continuously add tasks to the queue, this case is likely to lead to memory overflow problem for task too much,

3. NewCachedThreadPool analysis


Combining the above flow chart, the core number of threads=0, maximum thread is infinite, because SynchronousQueue will is a blocking queue cache value is 1, when there is a large number of tasks request, the thread pool creates a large number of threads, causing OOM,

Parameters of the thread pool, a

1. The constructor

/* * * @ param corePoolSize the core number of threads * @ param maximumPoolSize maximum number of threads * @ param keepAliveTime thread is allowed to idle time * @ param unit threads allowed by the idle time of the unit * @ param workQueue thread pool used by the buffer queue * @ param handler thread pool of reject the task processing policy */ThreadPoolExecutor (int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue WorkQueue, RejectedExecutionHandler handler)

2. The thread pool to refuse strategy

RejectedExecutionHandler strategy (saturation) : when the queue and the thread pool is full, the thread pool in saturated state, so must adopt a strategy of dealing with the submitted new tasks, the strategy is by default AbortPolicy, said can't handle an exception is thrown when a new task, and below is JDK1.5 provides four strategies,

AbortPolicy: an exception is thrown directly

CallerRunsPolicy: only the caller's thread to run the task,

DiscardOldestPolicy: discard a recent task in the queue, and perform the task,

DiscardPolicy: no treatment, discarded,

, of course, also can need according to application scenario to implement custom RejectedExecutionHandler interface strategy, such as logging or persistence can't handle tasks,

The thread pool open right way

1. Create a thread pool

Avoid using Executors to create a thread pool, main is to avoid using the default implementation, so we can direct call our ThreadPoolExecutor constructor to create your own thread pool, at the same time, create for BlockQueue specified capacity is ok,

ThreadPoolExecutor executorService=new ThreadPoolExecutor (8, 16 and 60, TimeUnit. SECONDS, new LinkedBlockingDeque<> (10));

2. Submit a task to a thread pool

We can use the execute submitted task, but the execute method has no return value, so I can't know by thread pool implementation success judgment tasks, using the following code shows the execute method of input task is a Runnable class instance,

ThreadPoolExecutor ThreadPoolExecutor=new ThreadPoolExecutor (5, 10, 20, TimeUnit. SECONDS, new LinkedBlockingDeque<> (60)); ThreadPoolExecutor. Execute (new Runnable () {@ Override public void the run () {System. Out. Println (" thread pool without return results "); }}); Copy ErrorCopied

We can also use the submit method to submit a task, it will return a future, so we can use the future to judge whether the task execution success, through the get method to obtain the return value of the future, the get method will block until the task is complete, and using the get (long timeout, TimeUnit unit) will be blocked immediately after a period of time () method returns, the possible task is not performed,

ThreadPoolExecutor ThreadPoolExecutor=new ThreadPoolExecutor (5, 10, 20, TimeUnit. SECONDS, new LinkedBlockingDeque<> (60)); Future Future=threadPoolExecutor. Submit (new Callable Call () () {@ Override public String throws the Exception {return "ok". }}); System. The out. Println (" thread pool to return the result: "+ future. The get ());

3. Close the thread pool

Shutdown close the thread pool

Method definition: public void shutdown ()

(1) the state of the thread pool into a state of SHUTDOWN, can't again to add a new task in the thread pool at this time, otherwise you will be thrown RejectedExecutionException abnormalities,

(2) the thread pool will not exit immediately, until all the tasks in the added to the thread pool has been processing is completed, will withdraw from,

This function will not wait for the notice to submit the task completed, if you want to wait for all tasks completed, you can call:

Public Boolean awaitTermination (longtimeout, TimeUnit unit)

ShutdownNow close thread pool and interrupt task

Method definition: public List shutdownNow ()

(1) the state of the thread pool to STOP immediately, at this time can't again to add a new task in the thread pool,

(2) the termination of the waiting thread of execution, and returns a list of them;

(3) try to stop all the Thread is executing, tries to approach is the Thread. The interrupt (), but you know, if not sleep in the Thread, wait, Condition, time lock applications, such as interrupt () method cannot be interrupted the current Thread, so ShutdownNow () does not mean the Thread pool can exit will immediately, it may have to wait all executing task execution completed to exit,

4. How to configure the thread pool size

Cpu-intensive task

This task requires a lot of operations, and there is no obstruction, CPU has been running at full speed, CPU intensive tasks only in real multi-core CPU configuration could accelerate through multi-threading CPU intensive tasks, as little as possible the number of threads:

Number of CPU cores + 1 thread thread pool,

For example: CPU 16 nuclear, 32 gb memory, number of threads=16

IO intensive tasks

IO intensive task threads were not always perform a task, the thread should be configured as much as possible, such as number of CPU cores * 2

A giant set strategy: IO intensive, most of the threads are blocked, so need more configuration threads:

Number of CPU cores/(1 - block coefficient)

For example: CPU cores, 16 block coefficient 0.9 -- -- -- -- -- -- -- -- -- -- -- -- -- & gt; 16/(1-0.9)=160 threads,

Nonblocking threads=at this time
  • Related