Java class libraries concurrent thread pool

new Thread malpractice

  • Frequent create threads and to destroy threads need time, greatly reduce the efficiency of the system
  • Lack of unified management, new objects may be unrestricted, compete with each other, resulting in too many system resources occupancy
  • Lack of execution more regularly executed, interrupt threads, and much more

Benefits thread pool

  • Reducing the number of creating and destroying threads, the thread can be reused, can perform multiple tasks
  • The maximum number of concurrent control, improving system resource utilization
  • Avoid excessive competition for resources, avoid blocking
  • Providing a regular basis, single-threaded, concurrent control and other functions

The life cycle of the thread pool

Thread Pool Lifecycle

ThreadPoolExecutor core classes


public class ThreadPoolExecutor extends AbstractExecutorService {

    // 包含 4 个构造方法。 其他 3 个通过调用该构造方法。

    public ThreadPoolExecutor(
        int corePoolSize,                       // 核心线程数量
        int maximumPoolSize,                   // 最大线程数
        long keepAliveTime,                    // 线程没有执行任务时最大保持多久终止
        TimeUnit unit,                         // keepAliveTime的时间单位
        BlockingQueue<Runnable> workQueue,     // 阻塞队列,存储等待执行的任务
        ThreadFactory threadFactory,           // 线程工厂,用来创建线程
        RejectedExecutionHandler handler       // 当拒绝处理任务时的策略
    ) { }

}
复制代码

The core argument constructor

int corePoolSize

The core number of threads.

After the default, create a thread pool, the number of threads in the thread pool is 0, when there are tasks to later, it will create a thread to perform the task, when the number of threads in the thread pool reaches corePoolSize, will be the arrival of mission into the cache queue (workQueue) them.

int maximumPoolSize

The maximum number of threads. To create the maximum number of threads in the thread pool.

int keepAliveTime

There is no maximum to maintain long thread termination duty.

By default, only when the number of threads in the thread pool greater than corePoolSize, keepAliveTime will work.

Call allowCoreThreadTimeOut (boolean) method, when the number of threads in the thread pool is not more than corePoolSize, keepAliveTime parameters come into play until the number of threads in the thread pool is zero.

TimeUnit unit

Parameters keepAliveTime time unit

TimeUnit.DAYS;               //天
TimeUnit.HOURS;             //小时
TimeUnit.MINUTES;           //分钟
TimeUnit.SECONDS;           //秒
TimeUnit.MILLISECONDS;      //毫秒
TimeUnit.MICROSECONDS;      //微妙
TimeUnit.NANOSECONDS;       //纳秒
复制代码

BlockingQueue workQueue

Task blocking queue, waiting to be executed is stored, have a significant impact on the process thread pool to run.

  • ArrayBlockingQueue
  • LinkedBlockingQueue
  • SynchronousQueue

ThreadFactory threadFactory

Thread factory used to create the main thread.

RejectedExecutionHandler handler

When the strategy is refusing to process tasks when.

// 丢弃任务,并抛出 RejectedExecutionException
ThreadPoolExecutor.AbortPolicy
// 丢弃任务,不抛出异常
ThreadPoolExecutor.DiscardPolicy
// 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.DiscardOldestPolicy
// 调用线程处理该任务
ThreadPoolExecutor.CallerRunsPolicy
复制代码

Internal work processes and interaction thread pool thread pool

Internal work processes and interaction thread pool thread pool

ThreadPoolExecutor common method

public class ThreadPoolExecutor extends AbstractExecutorService {
    // 提交任务,交给线程池执行
    public void execute(Runnable command) {}

    // 提交任务,能够返回执行结果 (execute + Future)
    public Future<?> submit(Runnable task) {}
    public <T> Future<T> submit(Runnable task, T result) {}
    public <T> Future<T> submit(Callable<T> task) {}

    // 关闭线程池,等待任务执行完
    public void shutdown() {}
            
    // 立即关闭,不等待任务关闭        
    public void shutdownNow() {}

    // 获得线程池中已执行和未执行的任务总数
    public long getTaskCount() {}

    // 获得已完成任务数量
    public long getCompletedTaskCount() {}

    // 线程池当前的线程数量
    public int getPoolSize() {}

    // 获得当前线程池中正在执行的线程数量
    public int getActiveCount() {
}
复制代码

Built-in thread pool


  • newSingleThreadExecutor ()
  • newFixedThreadPooll(int nThreads)
  • newCachedThreadPool()
  • newScheduledThreadPool(int corePoolSize) / newSingleThreadScheduledExecutor()
  • newWorkStealingPool(int parallelism)

Creation method of creating different configurations of thread pool with a general purpose thread pool Executors provided, the main difference lies in the different types or different ExecutorService initial parameters.

Thread pool class diagram

newSingleThreadExecutor ()

  • Creating a single-threaded thread pool
  • Only one thread at work to ensure the implementation of all tasks of the execution order submitted in accordance with the task order
  • Most existing programs are single threaded GUI
  • Android can be used in single-threaded database operations, file operations, batch application is installed, the application volume delete but not suitable for concurrent IO obstructive and may affect the operation of the UI thread responsive
public static void main(String[] args) {

    ExecutorService pool = Executors.newSingleThreadExecutor();

    // 执行过程将会顺序输出 0 --> 9
    for (int i = 0; i < 10; i++) {
        final int index = i;
        executorService.execute(() -> {
            System.out.println(index);
        })
    }
}
复制代码
// corePoolSize = 1
// maximumPoolSIze = 1
// keyAliveTime = 0L
// unit = TimeUnit.MILLISECONDS
// workQueue = new LinkedBlockingQueue<Runnable>()
// threadFactory = Executors.defaultThreadFactory()
// handler = defaultHandler = new AbortPolicy()
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
复制代码

newFixedThreadPooll(int nThreads)

  • Create a fixed-size thread pool, each time you submit a task to create a thread until it reaches nThreads
  • The size of the thread pool once they reach nThreads remains unchanged, because if a thread execution abnormal end, would add a new thread pool thread
  • Can control the maximum number of concurrent threads, excess threads will wait in the queue
public static void main(String[] args) {
    // 线程池大小为3
    ExecutorService executorService = Executors.newFixedThreadPool(3);

    // 每隔秒打印三个数字
    for (int i = 0; i < 50; i++) {
        final int index = i;
        executorService.execute(() -> {
            System.out.println(index);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }
    executorService.shutdown();
}
复制代码
// corePoolSize = nThreads
// maximumPoolSIze = nThreads
// keyAliveTime = 0L
// unit = TimeUnit.MILLISECONDS
// workQueue = new LinkedBlockingQueue<Runnable>()
// threadFactory = Executors.defaultThreadFactory()
// handler = defaultHandler = new AbortPolicy()
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
            0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
}
复制代码

newCachedThreadPool()

  • Creates a cached thread pool
  • The size of the thread pool threads exceeds the processing tasks required, it will recover partially free (60s) thread
  • When increasing the number of tasks, this thread pool can add a new thread to handle the task of intelligence
  • This thread pool do not restrict the size of the thread pool, thread pool thread maximum size depends entirely on the size of the operating system (or JVM) that can be created
public static void main(String[] args) {
    ExecutorService executorService = Executors.newCachedThreadPool();

    for (int i = 0; i < 10; i++) {
        final int index = i;
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(index);
            }
        });
    }

    executorService.shuntdown();
}
复制代码
// corePoolSize = 0
// maximumPoolSIze = Integer.MAX_VALUE
// keyAliveTime = 60L
// unit = TimeUnit.MILLISECONDS
// workQueue = new LinkedBlockingQueue<Runnable>()
// threadFactory = Executors.defaultThreadFactory()
// handler = defaultHandler = new AbortPolicy()
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
                                new SynchronousQueue<Runnable>());
}
复制代码

newScheduledThreadPool(int corePoolSize) / newSingleThreadScheduledExecutor()

  • Create an unlimited size of the thread pool
  • Support for regular and periodic tasks demand
public static void main(String[] args) {
    // new ScheduledThreadPoolExecutor(corePoolSize)
    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);

    // executorService 执行具有调度含义
    // delay: 3  SECONDS 后执行
	executorService.schedule(() -> System.out.println("schedule running"), 2, TimeUnit.SECONDS);

    executorService.shutdown();
}
复制代码
public static void main(String[] args) {
    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
    
    // executorService 执行具有调度含义
    // scheduleAtFixedRate 以指定的速率运行 每隔一段时候就触发
    // 1: initalDelay 延迟1秒
    // 3: period 每格3秒
    executorService.scheduleAtFixedRate(() -> System.out.println(System.nanoTime()), 1, 3, TimeUnit.SECONDS);

    // 不适用关闭线程池
    // 若需要关闭线程池,可通过提供关闭信息,再调用该方法
    // executorService.shutdown();
}
复制代码
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

// --- 

// DEFAULT_KEEPALIVE_MILLIS = 10L
// MILLISECONDS = TimeUnit.MILLI_SCALE
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE,
            DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
            new DelayedWorkQueue());
}
复制代码

newWorkStealingPool(int parallelism)

Java 8 before adding this to create a method that builds internal ForkJoinPool, the use of Work-Stealing algorithm, parallel processing tasks (the default is the number of available host CPU core), does not guarantee the processing order

public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
}

// --- 

public ForkJoinPool(int parallelism,
                        ForkJoinWorkerThreadFactory factory,
                        UncaughtExceptionHandler handler,
                        boolean asyncMode) {

    this(checkParallelism(parallelism),
            checkFactory(factory),
            handler,
            asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
            "ForkJoinPool-" + nextPoolId() + "-worker-");

    checkPermission();
}
复制代码

Configure thread pool


We need more practical situation.

  • CPU-intensive tasks

CPU needs to squeeze as much as possible. Reference may be N / N + 1 (N: the number of CPU)

  • IO-intensive

= CPU can refer to the number of threads auditor × (1 + the average waiting time / average working time)

Reference Reading


www.cnblogs.com/kuoAT/p/671…

www.cnblogs.com/dolphin0520…

Guess you like

Origin juejin.im/post/5d4d289051882515fd6bd519