JAVA implements four ways of multi-threading and ThreadPoolExecutor thread pool content detailed explanation of seven parameters rejection strategy custom thread pool

Detailed analysis of thread pool in four ways of JAVA multithreading

JAVA multithreading four ways

4 ways to implement threads in java:

  • 1. Inherit the Thread class and override the run method
  • 2. Implement the Runnable interface and implement the run method
  • 3. Inherit the Callable interface to implement the call method and use futureTask to call (with return value/can handle exceptions)

[The above three types are not used in normal business codes.]

[All multi-threaded asynchronous tasks should be handed over to the thread pool for execution]

  • 4. Thread pool (thread reuse; control the maximum number of concurrent; manage threads)

    • Reduce resource consumption

      • Reduce the loss caused by thread creation and destruction by reusing already created threads
    • Improve response speed

      • Because the number of threads in the thread pool does not exceed the maximum limit, some threads are in a state of waiting for tasks to be assigned, and when tasks come, they can be executed without creating new threads.
    • Improve thread manageability

      • The thread pool will optimize the threads in the pool according to the characteristics of the current system to reduce the system overhead caused by creating and destroying threads. Wireless creation and destruction of threads not only reduce system resources, but also reduce the stability of the system, and use the thread pool for uniformity distribution

1. Inherit the Thread class and override the run method

public class ThreadTest {
    
    
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
//        1.继承Thread类 重写run方法
        new Thread01().start();
        System.out.println("main end ....");
    }
    public static class Thread01 extends  Thread{
    
    
        @Override
        public void run() {
    
    
            System.out.println("1.继承Thread类 重写run方法");
        }
    }
}

2. Implement the Runnable interface and implement the run method

public class ThreadTest {
    
    
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
//         2.实现Runnable接口 实现run方法
        new Thread(new Runnable01()).start();
        System.out.println("main end ....");
    }
    public static class Runnable01 implements  Runnable{
    
    
        @Override
        public void run() {
    
    
            System.out.println("2.实现Runnable接口 实现run方法");
        }
    }
}

3. Inherit the Callable interface to implement the call method and use futureTask to call (with return value/can handle exceptions)

public class ThreadTest {
    
    
    public  static void main(String args[]) throws ExecutionException, InterruptedException {
    
    
        System.out.println("main start ....");
//        3.继承Callable接口 实现call方法 使用futureTask调用  (有返回值/可处理异常)
        Callable01 callable01 = new Callable01();
        FutureTask<Integer> futureTask = new FutureTask<>(callable01);
        new Thread(futureTask).start();
        //使用futureTask 获取返回值  会阻塞等待
        System.out.println(futureTask.get());
        System.out.println("main end ....");
    }
    public static class Callable01 implements Callable<Integer>{
    
    

        @Override
        public Integer call() throws Exception {
    
    
            System.out.println("3.继承Callable接口 实现call方法 使用futureTask调用  (有返回值/可处理异常)");
            return new Integer(200);
        }
    }
}

4. Thread pool

4.1 Application of basic thread pool

public class ThreadTest {
    
    
    //正常情况保证一个项目中只有少数线程池,每个异步任务,线程池让他自己取执行
    //Executors.newFixedThreadPool(10); 使用工具类生成容量为10的线程池
    //自定义线程池使用  new ThreadPoolExecutor();  自定义七大参数
    public static ExecutorService service = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
        try{
    
    
            service.execute(()->{
    
    
                System.out.println("4.线程池");
            });
        }catch (Exception e){
    
    
                e.printStackTrace();
        }finally{
    
    
            service.shutdown();
        }
        System.out.println("main end ....");
    }

}

4.2 Executors auxiliary tools

Executors.newFixedThreadPool(int);  //创建固定容量的线程池
Executors.newSingleThreadExecutor();  //创建一个只有1个工作线程的线程池
Executors.newCachedThreadPool() //创建一个可扩容的线程池。执行很多短期异步任务,线程池根据需要创建新线程,但在先前构造的线程可用时将重用他们。可扩容。
public class MyThreadPoolDemo {
    
    
    public  static void main(String args[]){
    
    
        //固定容量的线程池
//        ExecutorService threadPool =Executors.newFixedThreadPool(5); //创建一个有5个工作线程的线程池
//        ExecutorService threadPool =Executors.newSingleThreadExecutor(); //创建一个只有1个工作线程的线程池
        ExecutorService threadPool =Executors.newCachedThreadPool();  //创建一个可扩容的线程池
        try{
    
    
            for (int i = 1; i <10; i++) {
    
    
                //从线程池中使用一个工作线程
                threadPool.execute(()->{
    
    
                    System.out.println(Thread.currentThread().getName());
                });
            }
        }catch (Exception e){
    
    

        }finally{
    
    
            //任务结束 归还线程
            threadPool.shutdown();
        }
    }
}

The bottom layers of the above three Executors APIs are implemented using ThreadPoolExecutor with different parameters.
Insert picture description here

4.3 Analysis of the seven parameters of ThreadPoolExecutor

Insert picture description here

  • 1.corePoolSize: The number of resident core threads in the thread

  • 2, maxmunPoolSize: the maximum number of threads that can be executed simultaneously in the thread pool, this value must be greater than 1

  • 3. KeepAliveTime: The survival time of redundant idle threads. When the number of threads in the current pool exceeds corePoolSize && when the idle time reaches keepAliveTime, the extra threads will be destroyed until corePoolSize threads are left (excess strategy)

  • 4. unit: keepAliveTime unit

  • 5. workQueue: task blocking queue, tasks that have been submitted but not yet executed (not enough strategy)

  • 6, threadFactory: Represents the thread factory that generates worker threads in the thread pool, and is used to create threads. Generally the default is fine

  • 7. Handler: Rejection strategy, which means that when the task blocking queue is full, and the total number of working threads is greater than or equal to the maximum number of threads in the thread pool (maxmunPoolSize), how to refuse the Runnable strategy (full strategy) requested for execution

4.4 Working principle of ThreadPoolExecutor

  • 1. After creating the thread pool, start waiting for requests.

  • 2. When calling the execute() method to add a request task, the thread pool will make the following judgments:

    ​ 2.1 If the number of running threads is less than corePoolSize, then immediately create a thread to run this task;

    ​ 2.2 If the number of running threads is greater than or equal to corePoolSize, then put the task into the queue;

    ​ 2.3 If the queue is full at this time and the number of running threads is still less than the maximumPoolSize, then you still have to create a non-core thread to run this task immediately;

    ​ 2.4 If the queue is full and the number of running threads is greater than or equal to maximumPoolSize, then the thread pool will start the saturation rejection strategy to execute.

  • 3. When a thread completes its task, it will remove the next task from the queue for execution.

  • 4. When a thread has nothing to do for more than a certain period of time (keepAliveTime), the thread will judge:
    if the number of currently running threads is greater than corePoolSize, then this thread will be stopped.
    So after all tasks of the thread pool are completed, it will eventually shrink to the size of corePoolSize.

4.5 Custom thread pool

Use 7 parameters to customize the thread pool (the most important parameter is the rejection strategy)

public class MyThreadPoolDemo {
    
    
    public  static void main(String args[]){
    
    
       ExecutorService threadPool = new ThreadPoolExecutor(2,
                5,
                2L,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

Four major rejection strategies:

1. ThreadPoolExecutor.AbortPolicy(); throws RejectExecutionException directly to prevent the system from running normally

2. ThreadPoolExecutor.CallerRunsPolicy(); The caller runs an adjustment mechanism. This strategy neither abandons tasks nor throws exceptions, but returns certain tasks to the caller, thereby reducing the flow of new tasks

3. ThreadPoolExecutor.DiscardOldestPolicy(); Discard the longest waiting task in the queue, then add the current task to the queue and try to submit the current task again

4. ThreadPoolExecutor.DiscardPolicy(); This strategy silently discards tasks that cannot be processed, does not handle any tasks or throws exceptions. If the task is allowed to be lost, this is the best strategy.

Mechanism, this strategy neither abandons tasks nor throws exceptions, but returns certain tasks to the caller, thereby reducing the flow of new tasks

3. ThreadPoolExecutor.DiscardOldestPolicy(); Discard the longest waiting task in the queue, then add the current task to the queue and try to submit the current task again

4. ThreadPoolExecutor.DiscardPolicy(); This strategy silently discards tasks that cannot be processed, does not handle any tasks or throws exceptions. If the task is allowed to be lost, this is the best strategy.

Guess you like

Origin blog.csdn.net/weixin_44634197/article/details/108345736
Recommended