线程池必会

HeJin大约 4 分钟JavaJUC并发编程

3大方法、7大参数、4种拒绝策略。

image-20210312135440655
image-20210312135440655

三大方法

// 单个线程
Executors.newSingleThreadExecutor();
// 创建固定的线程池大小
Executors.newFixedThreadPool(5);
// 可伸缩的
Executors.newCachedThreadPool();

使用线程池来创建线程。

newSingleThreadExecutor

public class Demo01 {
    public static void main(String[] args) {
        // 单个线程
        ExecutorService threadPool = Executors.newSingleThreadExecutor();

        try {
            for (int i = 0; i < 10; i++) {
                // 使用线程池来创建线程。
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " ok");
                });
            }
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }
    }
}

结果:

pool-1-thread-1 ok
pool-1-thread-1 ok
pool-1-thread-1 ok
pool-1-thread-1 ok
pool-1-thread-1 ok
pool-1-thread-1 ok
pool-1-thread-1 ok
pool-1-thread-1 ok
pool-1-thread-1 ok
pool-1-thread-1 ok

Process finished with exit code 0

newFixedThreadPool

ExecutorService threadPool = Executors.newFixedThreadPool(5);

结果:

pool-1-thread-1 ok
pool-1-thread-2 ok
pool-1-thread-3 ok
pool-1-thread-4 ok
pool-1-thread-4 ok
pool-1-thread-5 ok
pool-1-thread-1 ok
pool-1-thread-3 ok
pool-1-thread-2 ok
pool-1-thread-4 ok

Process finished with exit code 0

newCachedThreadPool

ExecutorService threadPool = Executors.newCachedThreadPool();
pool-1-thread-1 ok
pool-1-thread-3 ok
pool-1-thread-2 ok
pool-1-thread-4 ok
pool-1-thread-5 ok
pool-1-thread-7 ok
pool-1-thread-8 ok
pool-1-thread-6 ok
pool-1-thread-9 ok
pool-1-thread-10 ok

Process finished with exit code 0

七大参数

源码分析

/** newSingleThreadExecutor **/
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

/** newFixedThreadPool **/
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

/** newCachedThreadPool **/
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

ThreadPoolExecutor

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.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

手动创建线程池

public class Demo01 {
    public static void main(String[] args) {
        // 自定义线程池
        ExecutorService threadPool = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                // 银行满了,还有人进来,不处理这个人的,抛出异常
                new ThreadPoolExecutor.AbortPolicy());

        try {
            // 最大承载:Queue + Max = 3 + 5 = 8
            for (int i = 1; i <= 9; i++) {
                // 使用线程池来创建线程。
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " ok");
                });
            }
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }
    }
}

核心工作人数:2。最大工作人数:5。待客区:3。

最大承载:Queue + Max = 3 + 5 = 8

1个人:

pool-1-thread-1 ok

Process finished with exit code 0

2个人

pool-1-thread-1 ok
pool-1-thread-2 ok

Process finished with exit code 0

3个人

pool-1-thread-1 ok
pool-1-thread-2 ok
pool-1-thread-1 ok

Process finished with exit code 0

4个人

pool-1-thread-2 ok
pool-1-thread-1 ok
pool-1-thread-2 ok
pool-1-thread-1 ok

Process finished with exit code 0

6个人

pool-1-thread-1 ok
pool-1-thread-3 ok
pool-1-thread-1 ok
pool-1-thread-1 ok
pool-1-thread-2 ok
pool-1-thread-3 ok

Process finished with exit code 0

7个人

pool-1-thread-2 ok
pool-1-thread-2 ok
pool-1-thread-2 ok
pool-1-thread-2 ok
pool-1-thread-4 ok
pool-1-thread-1 ok
pool-1-thread-3 ok

Process finished with exit code 0

8个人

pool-1-thread-1 ok
pool-1-thread-3 ok
pool-1-thread-2 ok
pool-1-thread-1 ok
pool-1-thread-4 ok
pool-1-thread-3 ok
pool-1-thread-5 ok
pool-1-thread-2 ok

Process finished with exit code 0

9个人

:超出最大承载

pool-1-thread-1 ok
pool-1-thread-5 ok
pool-1-thread-1 ok
pool-1-thread-4 ok
pool-1-thread-3 ok
pool-1-thread-2 ok
pool-1-thread-1 ok
pool-1-thread-5 ok
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.hejin.pool.Demo01$$Lambda$1/1747585824@58372a00 rejected from java.util.concurrent.ThreadPoolExecutor@4dd8dc3[Running, pool size = 5, active threads = 1, queued tasks = 0, completed tasks = 7]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
	at com.hejin.pool.Demo01.main(Demo01.java:27)

Process finished with exit code 1

四种拒绝策略

RejectedExecutionHandler接口

image-20210312142606783
image-20210312142606783

AbortPolicy

// 自定义线程池
ExecutorService threadPool = new ThreadPoolExecutor(
    2,
    5,
    3,
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(3),
    Executors.defaultThreadFactory(),
    // 银行满了,还有人进来,不处理这个人的,抛出异常
    new ThreadPoolExecutor.AbortPolicy());
pool-1-thread-1 ok
pool-1-thread-4 ok
pool-1-thread-2 ok
pool-1-thread-5 ok
pool-1-thread-2 ok
pool-1-thread-4 ok
pool-1-thread-1 ok
pool-1-thread-3 ok
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.hejin.pool.Demo01$$Lambda$1/1747585824@58372a00 rejected from java.util.concurrent.ThreadPoolExecutor@4dd8dc3[Running, pool size = 5, active threads = 0, queued tasks = 0, completed tasks = 8]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
	at com.hejin.pool.Demo01.main(Demo01.java:26)

Process finished with exit code 1

CallerRunsPolicy

// 自定义线程池
ExecutorService threadPool = new ThreadPoolExecutor(
        2,
        5,
        3,
        TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(3),
        Executors.defaultThreadFactory(),
        // 哪来的去哪里
        new ThreadPoolExecutor.CallerRunsPolicy());
pool-1-thread-1 ok
pool-1-thread-3 ok
pool-1-thread-4 ok
pool-1-thread-4 ok
pool-1-thread-2 ok
main ok
pool-1-thread-5 ok
pool-1-thread-3 ok
pool-1-thread-1 ok

Process finished with exit code 0

DiscardPolicy

// 自定义线程池
ExecutorService threadPool = new ThreadPoolExecutor(
        2,
        5,
        3,
        TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(3),
        Executors.defaultThreadFactory(),
        // 队列满了,丢掉任务,不会抛出异常
        new ThreadPoolExecutor.DiscardPolicy());
pool-1-thread-2 ok
pool-1-thread-5 ok
pool-1-thread-2 ok
pool-1-thread-4 ok
pool-1-thread-3 ok
pool-1-thread-1 ok
pool-1-thread-2 ok
pool-1-thread-5 ok

Process finished with exit code 0

DiscardOldestPolicy

// 自定义线程池
ExecutorService threadPool = new ThreadPoolExecutor(
        2,
        5,
        3,
        TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(3),
        Executors.defaultThreadFactory(),
        // 队列满了,尝试去和最早的竞争,也不会抛出异常
        new ThreadPoolExecutor.DiscardOldestPolicy());
pool-1-thread-1 ok
pool-1-thread-2 ok
pool-1-thread-1 ok
pool-1-thread-3 ok
pool-1-thread-4 ok
pool-1-thread-5 ok
pool-1-thread-1 ok
pool-1-thread-2 ok

Process finished with exit code 0