Java多线程-线程池ThreadPoolExecutor
为什么要使用线程池?
如果每个请求都创建一个线程去处理,那么服务器的CPU资源很快就会被耗尽,导致宕机。使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
线程池的作用
1)方便控制线程的数量,避免了因无休止的创建线程导致系统崩溃
2)减少了线程创建和消耗的时间
ThreadPoolExecutor创建线程池
示例:
/** * 线程池持有者单例 */ public class MyThreadPoolHolder { private static ThreadPoolExecutor executor; private MyThreadPoolHolder() { } public static ThreadPoolExecutor getInstance() { if (executor == null) { synchronized (MyThreadPoolHolder.class) { if (executor == null) { // Java虚拟机可用的CPU数量 int availableProcessor = Runtime.getRuntime().availableProcessors(); // 核心线程数 int corePoolSize = availableProcessor * 2 + 1; // 最大线程数 int maxPoolSize = corePoolSize * 2; // 线程存活时间 long keepAliveSeconds = 60L; // 线程队列容量 int queueCapacity = 1000; // 线程名称前缀 String threadNamePrefix = "MyThread - "; // 设置拒绝策略,默认是 ThreadPoolExecutor.AbortPolicy(),丢弃任务并抛出异常 RejectedExecutionHandler rejectPolicy = new ThreadPoolExecutor.AbortPolicy(); // 使用 ThreadPoolExecutor 创建线程池 executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveSeconds, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(queueCapacity), new MyThreadFactory(threadNamePrefix), rejectPolicy); } } } return executor; } } /** * 线程工程类 */ class MyThreadFactory implements ThreadFactory { /** * 线程名称前缀 */ private String threadNamePrefix; /** * 线程索引 */ private int threadIndex = -1; /** * 是否守护线程 */ private boolean isDaemon; public MyThreadFactory(String threadNamePrefix) { this.threadNamePrefix = threadNamePrefix; this.isDaemon = false; } public MyThreadFactory(String threadNamePrefix, boolean isDaemon) { this.threadNamePrefix = threadNamePrefix; this.isDaemon = isDaemon; } @Override public Thread newThread(Runnable target) { String threadName; synchronized (this) { threadIndex++; threadName = threadNamePrefix + threadIndex; } Thread thread = new Thread(target, threadName); thread.setDaemon(isDaemon); return thread; } }
使用线程池提交不需要返回值的任务
public class Test { public static void main(String[] args) { Runnable r1 = new Runnable() { @Override public void run() { for (int i = 1; i <= 10; i++) { System.out.println("r1执行,输出: " + i); } } }; Runnable r2 = new Runnable() { @Override public void run() { for (int i = 1; i <= 10; i++) { System.out.println("r2执行,输出: " + i); } } }; // 提交任务 MyThreadPoolHolder.getInstance().execute(r1); MyThreadPoolHolder.getInstance().execute(r2); } }
运行结果:
使用线程池提交需要返回值的任务
public class Test { public static void main(String[] args) throws InterruptedException, ExecutionException { Callable<List<String>> task1 = new Callable<List<String>>() { @Override public List<String> call() throws Exception { List<String> list = new ArrayList<>(); for (int i = 1; i <= 10; i++) { System.out.println("-----task1,运行----"); list.add("task1,值:" + i); } return list; } }; Callable<List<String>> task2 = new Callable<List<String>>() { @Override public List<String> call() throws Exception { List<String> list = new ArrayList<>(); for (int i = 1; i <= 10; i++) { System.out.println("-----task2,运行----"); list.add("task2,值:" + i); } return list; } }; // 提交任务 Future<List<String>> future1 = MyThreadPoolHolder.getInstance().submit(task1); Future<List<String>> future2 = MyThreadPoolHolder.getInstance().submit(task2); Thread.sleep(3000); System.out.println("任务提交之后,就开始运行了,并不是在Future.get()的时候才运行的"); // 合并结果 List<String> listRes = new ArrayList<>(); listRes.addAll(future1.get()); listRes.addAll(future2.get()); for (String item : listRes) { System.out.println(item); } } }
运行结果: