通过一次代码校验发现 线程池不建议使用Executors去创建,而是通过ThreadPoolExecutor方式的原因 顺便总结线程优缺点

今天在用P3C检查代码的时候发现这样一个警告:

首先用的是new Thread

public void doSummaryJob() throws Exception {
		try{
			HandlerMappingSummaryJobRunnable handlerMappingSummaryJobRunnable = new HandlerMappingSummaryJobRunnable();
			Thread summaryJobThread = new Thread(handlerMappingSummaryJobRunnable);
			summaryJobThread.start();
		}catch(Exception e){
			throw new Exception(HandlerMappingStaticValue.LOG_DO_SUMMARY_JOB_ERROR+e.getMessage());
		}
	}
然后爆出下面的建议



于是我改成Executors工厂创建线程池

HandlerMappingSummaryJobRunnable handlerMappingSummaryJobRunnable = new HandlerMappingSummaryJobRunnable();
			 // 定义一个线程池
		    ExecutorService executor = Executors.newCachedThreadPool();
		        executor.execute(() -> {
		            try {
		            	handlerMappingSummaryJobRunnable.run();//执行 方法
		            } catch (Exception e) {
		            	e.printStackTrace();
		            }finally{
		            	executor.shutdown();// 关闭线程池
		            }

        });

继续爆出下面的问题

线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。


最终我使用ThreadPoolExecutor

			//构造一个线程池
			ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
							1,1,10,TimeUnit.SECONDS, 
							new ArrayBlockingQueue<Runnable>(1),
							new ThreadPoolExecutor.DiscardOldestPolicy());
			threadPool.execute(() -> {
		            try {
		            		handlerMappingSummaryJobRunnable.run();//执行 方法
		            } catch (Exception e) {
		            	e.printStackTrace();
		            }finally{
	            	threadPool.shutdown();// 关闭线程池
		            }
	            });

阿里爸爸终于不再教育我了。。。

下面来看一下构造器,了解一下参数含义

//     public ThreadPoolExecutor(
//  int corePoolSize, - 线程池核心池的大小。
//                              int maximumPoolSize, - 线程池的最大线程数。
//                              long keepAliveTime, - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
//                              TimeUnit unit, - keepAliveTime 的时间单位。
//                              BlockingQueue<Runnable> workQueue, - 用来储存等待执行任务的队列。
//                              ThreadFactory threadFactory, - 线程工厂。

//                              RejectedExecutionHandler handler)  - 拒绝策略。

由此开始简要概述一下创建线程的几种方式及优劣

new Thread 方式

优势:显而易见的线程创建方式

缺点:每次都要new对象,当有大量请求时,数不清new了多少个对象了,如果不及时关闭会导致内存溢出,因此还要考虑线程管理等问题。

Executors工厂创建线程池

newCachedThreadPool:

创建一个可缓存线程池

优点:很灵活,弹性的线程池线程管理,用多少线程给多大的线程池,不用后及时回收,用则新建

缺点:一旦线程无限增长,会导致内存溢出。

newFixedThreadPool :

优点:创建一个固定大小线程池,超出的线程会在队列中等待。

缺点:不支持自定义拒绝策略,大小固定,难以扩展

newScheduledThreadPool :

优点:创建一个固定大小线程池,可以定时或周期性的执行任务。

缺点:任务是单线程方式执行,一旦一个任务失败其他任务也受影响

newSingleThreadExecutor :

优点:创建一个单线程的线程池,保证线程的顺序执行

缺点:不适合并发。。不懂为什么这种操作要用线程池。。为什么不直接用队列

统一缺点:不支持自定义拒绝策略。

通过ThreadPoolExecutor创建线程池

优点:集上述优点于一身

缺点:没发现缺点,因为上述线程池的底层就是通过它来创建的。。哈哈哈

上源码举个例子!

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());

    }

你会发现Executors的底层就是ThreadPoolExecutor。。只不过加了很多限制,剩下的自己翻源码去!!

猜你喜欢

转载自blog.csdn.net/qq_31615049/article/details/80756781