java multithreading of ThreadPoolExcutor

First, why the need to use the thread pool

  • Thread creation and destruction overhead is very high : frequent creating and destroying threads need to consume time, the response will slow down; while consuming computing resources.
  • Resource exhaustion : the idle thread will occupy memory, garbage collection will bring pressure on the competition thread CPU will also have performance overhead, can reasonably manage the thread pool idle threads
  • Stability : within a certain range, increasing the thread can enhance the processing capabilities of the system, if more than this range, continue to create threads only reduce the speed of execution, and even cause the system OOM, thread pool which can control the number of threads by the program.

Second, several common thread pool

First look at the constructor of the thread pool:

/**
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

复制代码
  1. newFixedThreadPool : to create a fixed-length thread pools , each time a new submission of a task to create a new thread, until the maximum number of threads in the pool, then the size of the thread pool is change (if a thread encountered an unexpected Exception The end of the thread pool would add a new thread).
 public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }
复制代码
  1. newCachedThreadPool : will create a cacheable thread pool , if there is an idle thread, the thread will reclaim free; if the task increases, you can add a new thread, the thread pool size of the absence of any boundaries.
 public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
复制代码
  1. newSingleThreadPool : to create a thread pool of single-threaded , if the thread ends abnormally, will create another thread to replace; blocking queue is LinkedBlockingQueue, the task can be executed in the order submitted
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
复制代码
  1. newScheduledThreadPool : Create a thread pool of fixed length, and delay or time in a manner to perform the task , like Timer.
    public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue(), threadFactory);
    }
复制代码

Third, the thread pool of six key parameters:

  1. corePoolSize : a core number of threads
    • The core thread will always survive, no task needs to be performed in a timely manner
    • The number of threads <when ​​corePoolSize, even with idle thread, the thread pool will create a new thread priority treatment
    • Set allowCoreThreadTimeout = true (default false), the core thread timeout Close
  2. queueCapacity : task queue capacity (blocking queue) when the core reaches the maximum number of threads, the new task will be placed in the queue are queued for execution
  3. maxPoolSize : maximum number of threads
    • The number of threads> = corePoolSize, and the task queue is full. Thread pool creates a new thread to handle the task
    • The number of threads = maxPoolSize, and the task queue is full, the thread pool will refuse to deal with the task and throw an exception
  4. keepAliveTime : thread idle time
    • When a thread is idle for keepAliveTime, the thread exits, until the number of threads = corePoolSize
    • If allowCoreThreadTimeout = true, it will until the number of threads = 0
  5. allowCoreThreadTimeout : allowing the core thread timeout
  6. RejectedExecutionHandler : Task refused processor, two cases will refuse processing tasks:
    • When a new task threads have reached maxPoolSize, cut the queue is full, it will reject
    • When the thread pool is called shutdown (), the thread pool will wait for the task is finished, and then shutdown. If you submit tasks between calls shutdown () thread pool and really shutdown, will refuse new tasks
    • It calls rejectedExecutionHandler thread pool to handle this task. If you do not set the default is AbortPolicy, throws an exception
  7. Refused strategy:
    • AbortPolicy direct throw a RejectedExecutionException, which is the default deny policy JDK
    • CallerRunsPolicy try to run tasks directly rejected, if the thread pool has been closed, the task is discarded
    • DiscardPolicy can not perform the task will be deleted
    • DiscardOldestPolicy removed the last of that task has not been processed, then perform the task rejected. Similarly, if the thread pool has been closed, the task is discarded
    • Custom: RejectedExecutionHandler implement the interface, the processor can be customized

Four, ThreadPoolExecutor order of execution:

 线程池按以下行为执行任务
复制代码
  1. currentThreadNum <corePoolSize-> create a thread.
  2. corePoolSize = <currentThreadNum, under the column, was added queue.
  3. corePoolSize = <currentThreadNum <maxPoolSize, and the task queue is full, creating a thread
  4. corePoolSize = <currentThreadNum && currentThreadNum> = maxPoolSize, and the task queue is full, create threads, throw an exception, refused to task

5, how to set parameters

  • 默认值 corePoolSize=1 queueCapacity=Integer.MAX_VALUE maxPoolSize=Integer.MAX_VALUE keepAliveTime=60s allowCoreThreadTimeout=false rejectedExecutionHandler=AbortPolicy()
  • How to set up
    1. We need to be determined according to several values
    • tasks: the task number per second, assuming 500 to 1000
    • taskcost: each task takes time, is assumed to be 0.1s
    • responsetime: set the maximum tolerable response time is assumed to 1s
    1. Do some calculation
    • corePoolSize = how many threads per process needs? threadcount = tasks / (1 / taskcost) = tasks * taskcout = (500 ~ 1000) * 0.1 = 50 ~ 100 threads. corePoolSize provided should be greater than 50 according to the principles of 8020, if 80% of the number of jobs is less than 800 per second, then set to 80 to corePoolSize
    • = queueCapacity (coreSizePool / taskcost) ResponseTime calculated = 80 can be obtained queueCapacity / 0.1 . 1 = 80. Meaning queue thread can wait for 1s, more than the need to open a new thread to perform remember not to Integer.MAX_VALUE, this queue will be great, just to keep the number of threads in corePoolSize size, increased sharply when the task is not new open thread to execute, the response time will follow increased sharply.
    • maxPoolSize = (max (tasks) - queueCapacity) / (1 / taskcost) can be calculated to obtain the maxPoolSize = (the maximum number of tasks - queue capacity) (1000-80) / 10 = 92 / sec for each thread processing capacity = the maximum number of threads
    • rejectedExecutionHandler: determined depending on the circumstances, it may be discarded important task, an important task will have to use some mechanism to deal with buffer
    • keepAliveTime and allowCoreThreadTimeout default usually suffices

Guess you like

Origin juejin.im/post/5d0115b6e51d4510617210b0