There are four kinds of thread pools that come with java

Which four types of thread pools are predefined by java?

  • newSingleThreadExecutor: thread pool with single thread number (core thread number = maximum thread number = 1)
  • newFixedThreadPool: A thread pool with a fixed number of threads (core threads = maximum threads = custom)
  • newCacheThreadPool: Cacheable thread pool (core threads=0, max threads=Integer.MAX_VALUE)
  • newScheduledThreadPool: Thread pool that supports timed or periodic tasks (core threads = custom, maximum threads = Integer.MAX_VALUE)

What is the difference between the four thread pools?

The above four thread pool classes all inherit ThreadPoolExecutor, and return new ThreadPoolExecutor (parameter) directly when they are created. The difference between them is that the parameters in the defined ThreadPoolExecutor (parameter) are different, and ThreadPoolExecutor inherits the ExecutorService interface class.

  • newFixedThreadPool
定义:
ExecutorService executorService=Executors.newFixedThreadPool(2);

Disadvantages: The linked list blocking queue of LinkBlockQueue is used. When the accumulation speed of tasks is greater than the processing speed, it is easy to accumulate tasks and cause OOM memory overflow

  • newSingleThreadExecutor
定义:ExecutorService executorService =Executors.newSingleThreadExecutor();

The above code is similar to new FixedThreadPoop(1), but it is different, because there is a layer of FinalizableDelegatedExecutorService outside, its function:

It can be seen that the essence of fixedExecutorService is ThreadPoolExecutor, so fixedExecutorService can be forcibly converted into ThreadPoolExecutor, but singleExecutorService has nothing to do with ThreadPoolExecutor, so the forced transfer fails, so after newSingleThreadExecutor() is created, its thread pool parameters cannot be modified, and it is truly single. single thread.

Disadvantages: The linked list blocking queue of LinkBlockQueue is used. When the accumulation speed of tasks is greater than the processing speed, it is easy to accumulate tasks and cause OOM memory overflow

  • newCacheThreadPool
定义:ExecutorService executorService=Executors.newCacheThreadPool();

Disadvantages: SynchronousQueue is an implementation of BlockingQueue, it is also a queue, because the maximum number of threads is Integer.MAX_VALUE, so when there are too many threads, it is easy to OOM memory overflow

  • ScheduledThreadPool
定义:ExecutorService executorService=Executors.newScheduledThreadPool(2);
Source code: 
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { 
        //ScheduledThreadPoolExecutor inherits ThreadPoolExecutor 
        return new ScheduledThreadPoolExecutor(corePoolSize); 
    } 
    
public ScheduledThreadPoolExecutor(int corePoolSize) { 
    //ScheduledThreadPoolExecutor inherits ThreadPoolExecutor, so super() will call the constructor of ThreadPoolExecutor to initialize and return A ThreadPoolExecutor, and ThreadPoolExecutor makes the implementation of the ExecutorService interface 
    // the final ScheduledThreadPoolExecutor also returns the implementation class of the ExecutorService interface like the above thread pools. ThreadPoolExecutor 
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, 
          new DelayedWorkQueue()); 
}

What are the important parameters of the thread pool?

The construction method of ThreadPoolExecutor is as follows:

  • keepAliveTime refers to how long these non-core threads whose current thread number is between [core thread number, maximum thread number] wait for idle time and exit the thread pool when there is no work;
  • The size of the waiting column has nothing to do with the maximum number of threads. Thread creation priority = core thread > blocking queue > expanded thread (threads can only be expanded when the current number of core threads is less than the maximum number of threads)
  • If the number of core threads is 5, the waiting queue length is 3, and the maximum number of threads is 10: when the number of threads continues to increase, 5 core threads are created first, and when the number of core threads is full, the threads are thrown into the waiting queue, and the waiting queue is full (3 threads), the maximum number of threads will be compared at this time (you can only appear after waiting for the maximum number of threads to be dropped), and you can continue to create 2 threads (5+3+2), if the number of threads exceeds the maximum number of threads , the rejection policy is executed;
  • If the number of core threads is 5, the length of the waiting queue is 3, and the maximum number of threads is 7: when the number of threads is increasing, 5 core threads are created first, and when the number of core threads is full, the threads are thrown into the waiting queue. When there are 2 threads, the maximum number of threads (5+2=7) is reached, but the waiting column is not full, so don't care about the maximum number of threads until the waiting column is full (3 blocked threads), at which time it will be the largest The number of threads (only the maximum number of threads can be displayed when the waiting column is full), at this time, the core + waiting for the column to be dropped = 5 + 3 = 8 > 7 = the maximum number of threads, that is, the maximum number of threads has been reached, and the rejection policy is executed;
  • If you set the waiting column to be dropped as LinkedBlockingQueue unbounded drop column, the dropped column is infinite, and you will never reach the step of judging the maximum number of threads.

How to customize the thread pool

Thread pools can be customized using bounded queues, custom thread creation factories, ThreadFactory, and rejection policy handlers

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException, IOException {
        int corePoolSize = 2;
        int maximumPoolSize = 4;
        long keepAliveTime = 10;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
        ThreadFactory threadFactory = new NameTreadFactory();
        RejectedExecutionHandler handler = new MyIgnorePolicy();
       ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit,
                workQueue, threadFactory, handler);
        executor.prestartAllCoreThreads(); // 预启动所有核心线程        
        for (int i = 1; i <= 10; i++) {
            MyTask task = new MyTask(String.valueOf(i));
            executor.execute(task);
        }
        System.in.read(); //阻塞主线程
    }
    static class NameTreadFactory implements ThreadFactory {
        private final AtomicInteger mThreadNum = new AtomicInteger(1);
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, "my-thread-" + mThreadNum.getAndIncrement());
            System.out.println(t.getName() + " has been created");
            return t;
        }
    }

    public static class MyIgnorePolicy implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            doLog(r, e); 
        } 
        private void doLog(Runnable r, ThreadPoolExecutor e) { 
            // Can do logging, etc. 
            System.err.println( r.toString() + " rejected"); 
// System.out.println ("completedTaskCount: " + e.getCompletedTaskCount()); 
        } 
    } 

    static class MyTask implements Runnable { 
        private String name; 
        public MyTask(String name) { 
            this.name = name; 
        } 
        @Override 
        public void run() { 
            try { 
            } catch (InterruptedException e) {
                System.out.println(this.toString() + " is running!");
                Thread.sleep(3000); //Slow the task execution 
                e.printStackTrace(); 
            } 
        } 
        public String getName() { 
            return name; 
        } 
        @Override 
        public String toString() { 
            return "MyTask [name=" + name + "]"; 
        } 
    } 
}

operation result:

Among them, threads 7-10 are rejected by the rejection policy. After threads 1 and 2 are executed, threads 3 and 6 enter the core thread pool for execution. At this time, threads 4 and 5 are waiting in the task queue for execution, while threads 3 and 6 execute. After finishing, notify 4 and 5 threads to execute

Guess you like

Origin blog.csdn.net/Trouvailless/article/details/124427132