Java多线程--创建和使用线程池

使用线程池的目的:

  • 线程是稀缺资源,不能频繁的创建。

  • 解耦作用;线程的创建于执行完全分开,方便维护。

  • 应当将其放入一个池子中,可以给其他任务进行复用。

创建线程池的方式:

 在 JDK 1.5 之后推出了相关的 api,常见的创建线程池方式有以下三种:

  • Executors.newCachedThreadPool():无限线程池。

  • Executors.newFixedThreadPool(nThreads):创建固定大小的线程池。

  • Executors.newSingleThreadExecutor():创建单个线程的线程池。

但是在阿里巴巴开发规约中对线程池的创建有以下几个强制要求:

可以看到规约是不允许使用Executors直接创建线程池的,而要通过ThreadPoolExecutor的方式创建

1 public static ExecutorService newCachedThreadPool() {
2         return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
3                                       60L, TimeUnit.SECONDS,
4                                       new SynchronousQueue<Runnable>());
5 }

我们看到这三种方式的源码也是通过ThreadPoolExecutor的方式来创建的,接下来我们看一下ThreadPoolExecutor的API

 1 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)  

这几个核心参数的作用:

  • corePoolSize 为线程池的基本大小。

  • maximumPoolSize 为线程池最大线程大小。

  • keepAliveTime 和 unit 则是线程空闲后的存活时间。

  • workQueue 用于存放任务的阻塞队列。

  • handler 当队列和最大线程池都满了之后的饱和策略。

 线程池大小创建的原则:

  • IO 密集型任务:由于线程并不是一直在运行,所以可以尽可能的多配置线程,比如 CPU 个数 * 2

  • CPU 密集型任务(大量复杂的运算)应当分配较少的线程,比如 CPU 个数相当的大小。

通过SpringBoot管理线程池:

 1 @Configuration
 2 public class TreadPoolConfig {
 3 
 4 
 5     /**
 6      * 消费队列线程
 7      * @return
 8      */
 9     @Bean(value = "consumerQueueThreadPool")
10     public ExecutorService buildConsumerQueueThreadPool(){
11         ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
12                 .setNameFormat("consumer-queue-thread-%d").build();
13 
14         ExecutorService pool = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
15                 new ArrayBlockingQueue<Runnable>(5),namedThreadFactory,new ThreadPoolExecutor.AbortPolicy());
16 
17         return pool ;
18     }
19 
20 
21 
22 }

使用:

 1   @Resource(name = "consumerQueueThreadPool")
 2     private ExecutorService consumerQueueThreadPool;
 3 
 4 
 5     @Override
 6     public void execute() {
 7 
 8         //消费队列
 9         for (int i = 0; i < 5; i++) {
10             consumerQueueThreadPool.execute(new ConsumerQueueThread());
11         }
12 
13     }

其实也挺简单,就是创建了一个线程池的 bean,在使用时直接从 Spring 中取出即可。

猜你喜欢

转载自www.cnblogs.com/ding-dang/p/11145684.html