根据阿里开发手册对线程池进行优化,
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,
这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
即添加一个线程工厂,将线程池放入线程工厂,主要是易于发现线程出错原因和定位,规避资源耗尽
说明:Executors 各个方法的弊端:
1)newFixedThreadPool 和 newSingleThreadExecutor:
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至 OOM。
2)newCachedThreadPool 和 newScheduledThreadPool:
主要问题是线程数最大数是 Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至 OOM。
ThreadPoolExecutor :
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
RejectedExecutionHandler handler 拒绝策略:
ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。 (默认)
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
改进成:
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("MQTT接收通道-%s").build(); ExecutorService pool = new ThreadPoolExecutor(5,200,20, TimeUnit.SECONDS,new SynchronousQueue<>(),namedThreadFactory,new ThreadPoolExecutor.AbortPolicy()); // 设置回调函数 client.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable cause) { System.out.println("connectionLost"); } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { System.out.println(message); //新建线程 放入任务 MyThread task = new MyThread(msgHandler,topic,message); //把线程任务丢给线程池处理 pool.execute(task); } @Override public void deliveryComplete(IMqttDeliveryToken token) { System.out.println("deliveryComplete---------"+ token.isComplete()); } });