The use of thread pool - how to create thread pool

Creation of thread pool

There are 7 ways to create a thread pool, but they can be generally divided into 2 categories:

  • One is the thread pool created by ThreadPoolExecutor;
  • Another class is a thread pool created by Executors.

How to create thread pool

Executors.newFixedThreadPool:

Create a thread pool with a fixed size, which can control the number of concurrent threads, and the excess threads will wait in the queue

//      创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        // 创建任务
        Runnable runnable = new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("任务被执行,线程:" + Thread.currentThread().getName());
            }
        };
            executorService.submit(runnable);  // 执行方式 1:submit
            executorService.execute(runnable); // 执行方式 2:execute
            executorService.execute(runnable);
            executorService.execute(runnable);
            //结束线程池
            executorService.shutdown();

The execution results are as follows:
tasks that exceed the number of threads will wait in the queue, and the thread execution tasks will be obtained after other tasks are executed.

任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-3
任务被执行,线程:pool-1-thread-2
任务被执行,线程:pool-1-thread-3

Executors.newCachedThreadPool:

Create a cacheable thread pool. If the number of threads exceeds the processing requirements, the cache will be recycled after a period of time. If the number of threads is not enough, a new thread will be created;

        ExecutorService executorService = Executors.newCachedThreadPool(Executors.defaultThreadFactory());
        // 创建任务
        Runnable runnable = new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("任务被执行,线程:" + Thread.currentThread().getName());
            }
        };
        // 线程池执行任务(一次添加 4 个任务)
        // 执行任务的方法有两种:submit 和 execute
        for (int i = 0; i < 10 ; i++) {
    
    
            executorService.submit(runnable);  // 执行方式 1:submit
            executorService.execute(runnable); // 执行方式 2:execute
            executorService.execute(runnable);
            executorService.execute(runnable);
        }
        executorService.shutdown();

The result of the operation is as follows:

任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-3
任务被执行,线程:pool-1-thread-4
任务被执行,线程:pool-1-thread-2
任务被执行,线程:pool-1-thread-5
任务被执行,线程:pool-1-thread-6
任务被执行,线程:pool-1-thread-7
任务被执行,线程:pool-1-thread-9
任务被执行,线程:pool-1-thread-10
任务被执行,线程:pool-1-thread-14
任务被执行,线程:pool-1-thread-13
任务被执行,线程:pool-1-thread-15
任务被执行,线程:pool-1-thread-16
任务被执行,线程:pool-1-thread-18
任务被执行,线程:pool-1-thread-20
任务被执行,线程:pool-1-thread-17
任务被执行,线程:pool-1-thread-22
任务被执行,线程:pool-1-thread-23
任务被执行,线程:pool-1-thread-25
任务被执行,线程:pool-1-thread-27
任务被执行,线程:pool-1-thread-28
任务被执行,线程:pool-1-thread-30
任务被执行,线程:pool-1-thread-29
任务被执行,线程:pool-1-thread-32
任务被执行,线程:pool-1-thread-31
任务被执行,线程:pool-1-thread-33
任务被执行,线程:pool-1-thread-35
任务被执行,线程:pool-1-thread-39
任务被执行,线程:pool-1-thread-36
任务被执行,线程:pool-1-thread-8
任务被执行,线程:pool-1-thread-19
任务被执行,线程:pool-1-thread-21
任务被执行,线程:pool-1-thread-24
任务被执行,线程:pool-1-thread-34
任务被执行,线程:pool-1-thread-38
任务被执行,线程:pool-1-thread-11
任务被执行,线程:pool-1-thread-12
任务被执行,线程:pool-1-thread-26
任务被执行,线程:pool-1-thread-37

Executors.newSingleThreadExecutor:

Create a thread pool with a single number of threads, which can guarantee the execution order of first-in-first-out;

  ExecutorService executorService = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());
        // 创建任务
        Runnable runnable = new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("任务被执行,线程:" + Thread.currentThread().getName());
            }
        };
        // 线程池执行任务(一次添加 4 个任务)
        // 执行任务的方法有两种:submit 和 execute
        for (int i = 0; i < 10 ; i++) {
    
    
            executorService.submit(runnable);  // 执行方式 1:submit
            executorService.execute(runnable); // 执行方式 2:execute
            executorService.execute(runnable);
            executorService.execute(runnable);
        }
        executorService.shutdown();

The execution results are as follows

任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
...

Executors.newScheduledThreadPool:

Create a thread pool that can execute delayed tasks;

      ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
       System.out.println("任务添加时间"+ new Date());
        ScheduledFuture<Date> schedul = scheduledExecutorService.schedule(()->{
    
    
            return new Date();
        }, 3, TimeUnit.SECONDS);
        System.out.println("任务执行完毕" + schedul.get());

The result of the operation is as follows:

Execute a task after 2 seconds, and the thread blocks waiting for the result to return. Ends when execution is complete and results are returned.

任务添加时间Thu Mar 02 20:50:12 CST 2023
任务执行完毕Thu Mar 02 20:50:15 CST 2023

Executors.newSingleThreadScheduledExecutor:

Create a single-threaded thread pool that can perform delayed tasks;

public static void SingleThreadScheduledExecutor() {
    
    
    // 创建线程池
    ScheduledExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();
    // 添加定时执行任务(2s 后执行)
    System.out.println("添加任务,时间:" + new Date());
    threadPool.schedule(() -> {
    
    
        System.out.println("任务被执行,时间:" + new Date());
        try {
    
    
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
    
    
        }
    }, 2, TimeUnit.SECONDS);
}

The execution results are as follows:
insert image description here

Executors.newWorkStealingPool:

Create a thread pool for preemptive execution (task execution order is uncertain) [JDK 1.8 added].

public static void workStealingPool() {
    
    
    // 创建线程池
    ExecutorService threadPool = Executors.newWorkStealingPool();
    // 执行任务
    for (int i = 0; i < 10; i++) {
    
    
        final int index = i;
        threadPool.execute(() -> {
    
    
            System.out.println(index + " 被执行,线程名:" + Thread.currentThread().getName());
        });
    }
    // 确保任务执行完成
    while (!threadPool.isTerminated()) {
    
    
    }
}

The running results are as follows:
From the above results, it can be seen that the execution order of tasks is uncertain because it is preemptively executed.
insert image description here

ThreadPoolExecutor:

The most primitive way to create a thread pool, it contains 7 parameters for setting.

public static void myThreadPoolExecutor() {
    
    
    // 创建线程池
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
    // 执行任务
    for (int i = 0; i < 10; i++) {
    
    
        final int index = i;
        threadPool.execute(() -> {
    
    
            System.out.println(index + " 被执行,线程名:" + Thread.currentThread().getName());
            try {
    
    
                Thread.sleep(1000);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        });
    }
}

The execution results are as follows:
insert image description here

The rejection policy of the thread pool

When the task cache queue of the thread pool is full and the number of threads in the thread pool reaches the maximumPoolSize, if there are tasks coming, the task rejection strategy will be adopted. Usually, there are the following four strategies:

ThreadPoolExecutor.AbortPolicy:

The task is discarded and a RejectedExecutionException is thrown.

ThreadPoolExecutor.DiscardPolicy:

Discard the task without throwing an exception.

ThreadPoolExecutor.DiscardOldestPolicy:

Discard the task at the front of the queue and resubmit the rejected task

ThreadPoolExecutor.CallerRunsPolicy:

The task is processed by the calling thread (the thread that submitted the task)

Guess you like

Origin blog.csdn.net/weixin_58286934/article/details/129307155