线程池
 
1.优点
 
  1. 降低资源消耗(线程复用)
  2. 提高响应速度
  3. 可管理线程
 
2.自定义线程池
 
public class ThreadPoolExecutorDemo {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,          
                4,      
                3,         
                TimeUnit.SECONDS,      
                new LinkedBlockingQueue<>(3),    
                Executors.defaultThreadFactory(),        
                
                
                new ThreadPoolExecutor.CallerRunsPolicy()      
                );
        try {
            for (int i = 1; i <= 100; i++) {
                threadPoolExecutor.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"==>");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPoolExecutor.shutdown();   
        }
    }
}
 
3.阻塞队列
 
ArrayBlockingQueue:基于数组结构的有界阻塞队列,按先进先出对元素进行排序。
LinkedBlockingQueue:基于链表结构的有界/无界阻塞队列,按先进先出对元素进行排序,吞吐量通常高于 ArrayBlockingQueue。Executors.newFixedThreadPool 使用了该队列。
SynchronousQueue:不是一个真正的队列,而是一种在线程之间移交的机制。要将一个元素放入 SynchronousQueue 中,必须有另一个线程正在等待接受这个元素。如果没有线程等待,并且线程池的当前大小小于最大值,那么线程池将创建一个线程,否则根据拒绝策略,这个任务将被拒绝。使用直接移交将更高效,因为任务会直接移交给执行它的线程,而不是被放在队列中,然后由工作线程从队列中提取任务。只有当线程池是无界的或者可以拒绝任务时,该队列才有实际价值。Executors.newCachedThreadPool使用了该队列。
PriorityBlockingQueue:具有优先级的无界队列,按优先级对元素进行排序。元素的优先级是通过自然顺序或 Comparator 来定义的。
 
4.拒绝策略
 
                new ThreadPoolExecutor.CallerRunsPolicy()      
 
5. 执行流程
 
先使用核心线程池处理任务,多余的任务放入阻塞队列中,队列满后使用救急线程,当线程数达到最大线程数后,使用拒绝策略
 
6.如何合理的配置线程池的最大线程数?
 
先判断是CPU密集型还是IO密集型
   CPU密集型,设置线程数 = CPU数 + 1,通常能实现最优的利用率
      Runtime.getRuntime().availableProcessors()     
   IO密集型,设置 线程数 = CPU数 * 2