• 线程池


    线程池

    通过例子理解

    • 例1
    package com.example.test;
    
    import com.google.common.util.concurrent.ThreadFactoryBuilder;
    
    import java.util.concurrent.*;
    
    /**
     * 核心线程数:5,最大线程数:10,有界阻塞队列长度:5
     *
     * @author mdl
     * @date 2020/5/14 14:21
     */
    public class ThreadPoolTest {
    
        public static void main(String[] args) {
            int corePoolSize = 5;
            int maximumPoolSize = 10;
            int queueSize = 5;
    
            ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-call-runner-%d").build();
            BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(queueSize);
            ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 0, TimeUnit.MILLISECONDS,
                    workQueue, namedThreadFactory, new MyIgnorePolicy());
    
            for(int i =0; i< 10 ;i++){
                executor.submit(new Handle());
            }
            // 效果:打印了前5个任务,10s后打印后5个任务
            // 结论1:来了5个任务(假定任务执行时间较长),这时再来任务,将进入阻塞队列,核心线程空闲时处理
            // ----------------------------------------------------
    
        }
    
        public static class MyIgnorePolicy implements RejectedExecutionHandler {
    
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.err.println(r.toString() + " rejected");
            }
        }
    
    
        static class Handle implements Runnable{
    
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "--- executor...");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    

    image-20200514145103136

    红框内的再10s后出现的

    结论:来了5个任务(假定任务执行时间较长),这时再来任务,将进入阻塞队列,核心线程空闲时处理

    • 例2

      package com.example.test;
      
      import com.google.common.util.concurrent.ThreadFactoryBuilder;
      
      import java.util.concurrent.*;
      
      /**
       * 核心线程数:5,最大线程数:10,有界阻塞队列长度:5
       *
       * @author mdl
       * @date 2020/5/14 14:21
       */
      public class ThreadPoolTest {
      
          public static void main(String[] args) {
              int corePoolSize = 5;
              int maximumPoolSize = 10;
              int queueSize = 5;
      
              ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-call-runner-%d").build();
              BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(queueSize);
              ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 0, TimeUnit.MILLISECONDS,
                      workQueue, namedThreadFactory, new MyIgnorePolicy());
      
      //        for(int i =0; i< 10 ;i++){
      //            executor.submit(new Handle());
      //        }
              // 效果:打印了前5个任务,10s后打印后5个任务
              // 结论1:来了5个任务(假定任务执行时间较长),这时再来任务,将进入阻塞队列,核心线程空闲时处理
              // ----------------------------------------------------
              for(int i =0; i< 15 ;i++){
                  executor.submit(new Handle());
              }
              // 效果:先打印了10个线程执行,10s后打印5个
              // 结论:第1~5进来的任务由核心线程执行,第6~10将进入阻塞任务队列,第11~15个任务由临时线程执行
              // 核心线程或者临时线程空闲出来后去取阻塞任务队列里的任务执行
          }
      
          public static class MyIgnorePolicy implements RejectedExecutionHandler {
      
              @Override
              public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                  System.err.println(r.toString() + " rejected");
              }
          }
          
          static class Handle implements Runnable{
      
              @Override
              public void run() {
                  System.out.println(Thread.currentThread().getName() + "--- executor...");
                  try {
                      Thread.sleep(10000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
      

      image-20200514145729556

    红框里的10s后才显示

    结论:第1~5进来的任务由核心线程执行,第6~10将进入阻塞任务队列,第11~15个任务由临时线程执行

    核心线程或者临时线程空闲出来后去取阻塞任务队列里的任务执行

    • 例3

      package com.example.test;
      
      import com.google.common.util.concurrent.ThreadFactoryBuilder;
      
      import java.util.concurrent.*;
      
      /**
       * 核心线程数:5,最大线程数:10,有界阻塞队列长度:5
       *
       * @author mdl
       * @date 2020/5/14 14:21
       */
      public class ThreadPoolTest {
      
          public static void main(String[] args) {
              int corePoolSize = 5;
              int maximumPoolSize = 10;
              int queueSize = 5;
      
              ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-call-runner-%d").build();
              BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(queueSize);
              ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 0, TimeUnit.MILLISECONDS,
                      workQueue, namedThreadFactory, new MyIgnorePolicy());
      
      //        for(int i =0; i< 10 ;i++){
      //            executor.submit(new Handle());
      //        }
              // 效果:打印了前5个任务,10s后打印后5个任务
              // 结论1:来了5个任务(假定任务执行时间较长),这时再来任务,将进入阻塞队列,核心线程空闲时处理
              // ----------------------------------------------------
      //        for(int i =0; i< 15 ;i++){
      //            executor.submit(new Handle());
      //        }
              // 效果:先打印了10个线程执行,10s后打印5个
              // 结论2:第1~5进来的任务由核心线程执行,第6~10将进入阻塞任务队列,第11~15个任务由临时线程执行
              // 核心线程或者临时线程空闲出来后去取阻塞任务队列里的任务执行
              for (int i = 0; i < 16; i++) {
                  executor.submit(new Handle());
              }
              // 效果跟2的区别就是第16个任务进来将执行解决策略
          }
      
          public static class MyIgnorePolicy implements RejectedExecutionHandler {
      
              @Override
              public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                  System.err.println(r.toString() + " rejected");
              }
          }
      
      
          static class Handle implements Runnable {
      
              @Override
              public void run() {
                  System.out.println(Thread.currentThread().getName() + "--- executor...");
                  try {
                      Thread.sleep(10000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
      

      image-20200514150122488

    红框里的10s后出现

    跟例2的区别是:第16个任务进来的时候将执行拒绝策略

    总结

    小于或等于corePoolSize: 创建核心线程处理任务

    大于corePoolSize且小于队列长度:进入阻塞队列

    大于corePoolSize+队列长度,小于maxPoolSize+队列长度:创建临时线程处理任务

    大于maxPoolSize+队列长度:执行拒绝策略

    核心线程和临时线程无论谁空闲出来就去阻塞队列里取任务执行

    配置

    • 高并发、任务执行时间短:线程数设置CPU核数+1(尽量少),目的是减少线程上下文切换
    • 高并发、任务执行时间长:
      1. 数据缓存
      2. 服务器集群
      3. 任务拆分,异步解耦
    • 并发低、任务执行时间长:
      1. 瓶颈在磁盘IO, 增加线程数,让CPU都动起来,可以设置CPU核数*2
      2. 业务计算密集(又叫CPU密集型),线程数设置的少些,减少线程上下文切换,配置CPU核数+1

    最大可用的处理器数量

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    
    每一步脚印都要扎得深一点!
  • 相关阅读:
    JQuery -- this 和 $(this) 的区别
    js动态生成表格
    Sublime 3 如何使用列编辑模式
    新版Sublime text3注册码被移除的解决办法
    Sublime text 3 格式化HTML/css/js/json代码 插件
    mingw64 构建 Geos
    C++调用Python浅析
    linux下挂载VHD等虚拟磁盘文件
    linux 下Qt WebEngine 程序打包简单记录
    C++ UTF8和UTF16互转代码
  • 原文地址:https://www.cnblogs.com/bloodthirsty/p/12890112.html
Copyright © 2020-2023  润新知