线程池创建方式详解

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的ThreadFactory创建一个新线程。

线程池的创建主要依赖于java.util.concurrent包下的ExecutorServiceExecutors类。最近面试问到了这块,所以这篇文章我们将详细介绍几种常见的线程池创建方式。

FixedThreadPool

FixedThreadPool是一种固定大小的线程池。它的核心线程数和最大线程数都是创建时指定的数值 ,且不会变化。就算空闲,也不会回收线程,除非设置了allowCoreThreadTimeOut

举个栗子:我们创建一个固定大小为5的线程池,并提交10个任务。由于线程池的大小固定为5,因此这5个线程会并发执行,而剩下的任务会等待前面的任务完成后再执行。

代码如下:

java 复制代码
	import java.util.concurrent.ExecutorService;  

	import java.util.concurrent.Executors;  

	  

	public class FixedThreadPoolDemo {  

	    public static void main(String[] args) {  

	        // 创建一个固定大小的线程池  

	        ExecutorService executorService = Executors.newFixedThreadPool(5);  

	  

	        for (int i = 0; i < 10; i++) {  

	            Runnable worker = new WorkerThread("" + i);  

	            executorService.execute(worker);  // 执行任务  

	        }  

	        executorService.shutdown();  // 关闭线程池  

	        while (!executorService.isTerminated()) {  

	        }  

	        System.out.println("所有任务已完成");  

	    }  

	}  

	  

	class WorkerThread implements Runnable {  

	    private String command;  

	  

	    public WorkerThread(String s) {  

	        this.command = s;  

	    }  

	  

	    @Override  

	    public void run() {  

	        System.out.println(Thread.currentThread().getName() + " 开始. 命令 = " + command);  

	        processCommand();  

	        System.out.println(Thread.currentThread().getName() + " 结束.");  

	    }  

	  

	    private void processCommand() {  

	        try {  

	            Thread.sleep(5000);  

	        } catch (InterruptedException e) {  

	            e.printStackTrace();  

	        }  

	    }  

	}

CachedThreadPool

CachedThreadPool是一种缓存线程池,它的线程数量是不定的,可以说是几乎无限的。当提交一个任务时,如果线程池中有空闲线程,则立即执行;如果没有,则创建一个新线程执行。当线程空闲超过60秒,则自动回收。

举个栗子:

java 复制代码
	import java.util.concurrent.ExecutorService;  

	import java.util.concurrent.Executors;  

	  

	public class CachedThreadPoolDemo {  

	    public static void main(String[] args) {  

	        // 创建一个可缓存的线程池  

	        ExecutorService executorService = Executors.newCachedThreadPool();  

	  

	        for (int i = 0; i < 10; i++) {  

	            Runnable worker = new WorkerThread("" + i);  

	            executorService.execute(worker);  // 执行任务  

	        }  

	        executorService.shutdown();  // 关闭线程池  

	        while (!executorService.isTerminated()) {  

	        }  

	        System.out.println("所有任务已完成");  

	    }  

	}

CachedThreadPool`适合执行大量的耗时较少的任务,如Web服务器。

SingleThreadExecutor

SingleThreadExecutor是一个单线程的Executor,它使用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。

java 复制代码
	import java.util.concurrent.ExecutorService;  

	import java.util.concurrent.Executors;  

	  

	public class SingleThreadExecutorDemo {  

	    public static void main(String[] args) {  

	        // 创建一个单线程的线程池  

	        ExecutorService executorService = Executors.newSingleThreadExecutor();  

	  

	        for (int i = 0; i < 10; i++) {  

	            Runnable worker = new WorkerThread("" + i);  

	            executorService.execute(worker);  // 执行任务  

	        }  

	        executorService.shutdown();  // 关闭线程池  

	        while (!executorService.isTerminated()) {  

	        }  

	        System.out.println("所有任务已完成");  

	    }  

	}

SingleThreadExecutor中,由于只有一个线程,因此任务会按照提交的顺序一个接一个地执行,不会出现并发的情况

ScheduledThreadPool

ScheduledThreadPool 是 Java 并发包 java.util.concurrent 中提供的一个线程池实现,它用于在给定的延迟后运行命令,或者定期地执行命令。ScheduledThreadPool 的主要特点是能够处理需要定时执行或周期性执行的任务

举个栗子:

java 复制代码
	import java.util.concurrent.Executors;  

	import java.util.concurrent.ScheduledExecutorService;  

	import java.util.concurrent.TimeUnit;  

	  

	public class ScheduledThreadPoolDemo {  

	    public static void main(String[] args) {  

	        // 创建一个ScheduledThreadPool,包含3个核心线程  

	        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);  

	  

	        // 提交一个Runnable任务,在延迟2秒后执行  

	        scheduledExecutorService.schedule(new RunnableTask("一次性任务"), 2, TimeUnit.SECONDS);  

	  

	        // 提交一个Runnable任务,初始延迟2秒,之后每隔1秒执行一次  

	        scheduledExecutorService.scheduleAtFixedRate(new RunnableTask("周期性任务"), 2, 1, TimeUnit.SECONDS);  

	  

	        // 通常我们需要在程序结束时关闭线程池  

	        // scheduledExecutorService.shutdown();  

	    }  

	  

	    static class RunnableTask implements Runnable {  

	        private String command;  

	  

	        public RunnableTask(String command) {  

	            this.command = command;  

	        }  

	  

	        @Override  

	        public void run() {  

	            System.out.println(Thread.currentThread().getName() + " 开始执行命令: " + command + " at " + System.currentTimeMillis());  

	        }  

	    }  

	}

我们创建了一个 ScheduledThreadPool,它包含3个核心线程。然后,我们提交了两个任务:

  1. 一个是一次性任务,它在提交后的2秒后开始执行。
  2. 另一个是周期性任务,它在提交后的2秒开始执行,然后每隔1秒执行一次。

除了以上的用法 ,ScheduledExecutorService 提供了几个用于定时执行任务的方法:

  • schedule(Runnable command, long delay, TimeUnit unit):在给定延迟后运行命令一次。
  • scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit):初始延迟后开始首次执行,然后随后每隔固定周期执行一次。
  • scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit):初始延迟后开始首次执行,然后每次执行完毕后等待固定延迟再次执行。

如果任务执行过程中抛出异常,那么 ScheduledThreadPool 会停止该任务的后续执行,但不会停止线程池本身或其他任务的执行。如果需要处理任务执行中的异常,可以在任务内部进行捕获和处理。

以上就是创建线程池的几种方式,本篇文章到此结束,谢谢大家的观看!

相关推荐
ZHOUZAIHUI1 小时前
WSL(Ubuntu24.04) 安装PostgreSQL
开发语言·后端·scala
i02082 小时前
SpringBoot 项目配置
java·spring boot·后端
月屯2 小时前
后端go完成文档分享链接功能
开发语言·后端·golang
Franciz小测测2 小时前
Python连接RabbitMQ三大方案全解析
开发语言·后端·ruby
海梨花3 小时前
又是秒杀又是高并发,你的接口真的扛得住吗?
java·后端·jmeter
Livingbody3 小时前
win11上wsl本地安装版本ubuntu25.10
后端
用户8356290780514 小时前
如何在 C# 中自动化生成 PDF 表格
后端·c#
星释4 小时前
Rust 练习册 44:Trait 中的同名函数调用
开发语言·后端·rust
京东零售技术4 小时前
并发丢数据深度剖析:JED的锁机制与事务实战踩坑及解决方案
后端
f***68604 小时前
问题:Flask应用中的用户会话(Session)管理失效
后端·python·flask