基于线程池的java多线程
摘自阿里java开发规范:
线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors 返回的线程池对象的弊端如下: 1)FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。 2)CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
ThreadPoolExecutor方式的几个构造函数需要明确指定最大线程数及等待队列的大小,资源饱和时提供了四种拒绝策略
AbortPolicy:ThreadPoolExecutor中默认的拒绝策略就是AbortPolicy。直接抛出异常。
CallerRunsPolicy:在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务。当前线程池所在线程执行被拒绝的任务期间不会请求添加新的任务,期间其他线程会消费队
列中的任务,为新任务腾出空间。此期间客户端发起的新任务会在网络上排队,时间如果太长则可能客户端任务会超时,但都与服务单无关。
DiscardPolicy:这个策略什么都没干,因此采用这个拒绝策略,会让被线程池拒绝的任务直接抛弃,不会抛异常也不会执行。会造成任务的丢失。
DiscardOldestPolicy:当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。会造成任务的丢失。
如果上述四种策略不能满足需求,ThreadPoolExecutor提供了自定义拒绝策略。通过继承RejectedExecutionHandler接口重写自己的拒绝策略。
package test; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class Test { private static Socket socket = null; public static void main(String[] args) { // TODO Auto-generated method stub ServerSocket server = null; // 核心线程数、最大线程数、非核心线程空闲存货时间、等待队列(定义大小) ThreadPoolExecutor threadPool = new ThreadPoolExecutor(50, 100, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1024000)); // 应用四种饱和拒绝策略 // threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); // 应用自定义饱和拒绝策略 threadPool.setRejectedExecutionHandler(new MyPolicy()); int port = 8011; try { server = new ServerSocket(port); while (true) { socket = server.accept(); threadPool.execute(new MyThread(socket)); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * @author Administrator 自定义线程池饱和拒绝策略 */ class MyPolicy implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // 自定义业务逻辑 } } /** * @author Administrator 自定义线程池饱和拒绝策略 */ class MyThread implements Runnable { private Socket socket = null; MyThread(Socket socket) { this.socket = socket; } @Override public void run() { // 业务逻辑 } }