Java线程池的用法(附带示例)
当系统中存在大量并发线程,且每个线程仅执行短暂任务时,频繁创建和销毁线程会显著降低系统效率。这是因为线程的创建和销毁过程本身消耗时间。
是否存在一种机制,能够使线程被重复利用呢?也就是说,线程在完成一个任务后,不立即销毁,而是继续执行其他任务。解决方案是预先创建一组线程,并将它们存储在所谓的线程池中。
当需要执行任务时,可以直接从线程池中获取线程,任务完成后,线程被归还到线程池中,从而避免了频繁创建和销毁过程,实现了对线程的复用。这与生活中的公共交通工具模式类似。
线程池如下图所示:

图 1 线程池
线程池具有以下优点:
【实例 1】创建线程池并利用线程池,代码如下:
是否存在一种机制,能够使线程被重复利用呢?也就是说,线程在完成一个任务后,不立即销毁,而是继续执行其他任务。解决方案是预先创建一组线程,并将它们存储在所谓的线程池中。
当需要执行任务时,可以直接从线程池中获取线程,任务完成后,线程被归还到线程池中,从而避免了频繁创建和销毁过程,实现了对线程的复用。这与生活中的公共交通工具模式类似。
线程池如下图所示:

图 1 线程池
线程池具有以下优点:
- 提高响应速度(减少创建新线程的时间);
- 降低资源消耗(重复利用线程池中的线程,不需要每次都创建线程);
- 便于线程管理。
线程池相关API
在 JDK 5.0 之前,我们必须手动自定义线程池。从 JDK 5.0 开始,Java 内置了与线程池相关的 API。java.util.concurrent 包中提供与线程池相关的 API——ExecutorService 和 Executors。1) ExecutorService
ExecutorService 是真正的线程池接口,常见子类为 ThreadPoolExecutor:- void execute(Runnable command):执行任务/命令,没有返回值,一般用来执行 Runnable;
- <T> Future<T> submit(Callable<T> task):执行任务,有返回值,一般用来执行 Callable;
- void shutdown():关闭连接池。
2) Executors
Executors 是一个线程池的工厂类,通过此类的静态工厂方法可以创建多种类型的线程池对象:- Executors.newCachedThreadPool():创建一个可以根据需要创建新线程的线程池。
- Executors.newFixedThreadPool(int nThreads):创建一个可以重用固定线程数的线程池。
- Executors.newSingleThreadExecutor():创建一个只有一个线程的线程池。
- Executors.newScheduledThreadPool(int corePoolSize):创建一个线程池,它可以在给定的延迟时间后运行命令或定期运行命令。
【实例 1】创建线程池并利用线程池,代码如下:
public class NumberThread implements Runnable { @Override public void run() { for (int i = 0; i <= 100; i++) { if (i % 2 == 0) { System.out.println(Thread.currentThread().getName() + ": " + i); } } } } public class NumberThread02 implements Runnable { @Override public void run() { for (int i = 0; i <= 100; i++) { if (i % 2 != 0) { System.out.println(Thread.currentThread().getName() + ": " + i); } } } } import java.util.concurrent.Callable; public class NumberThread03 implements Callable { @Override public Object call() throws Exception { int evenSum = 0; // 记录偶数的和 for (int i = 0; i <= 100; i++) { if (i % 2 == 0) { evenSum += i; } } return evenSum; } } import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; public class ThreadPoolTest { public static void main(String[] args) { // 1.提供指定线程数量的线程池 ExecutorService service = Executors.newFixedThreadPool(10); ThreadPoolExecutor service1 = (ThreadPoolExecutor) service; // 设置线程池的属性 System.out.println(service.getClass()); // ThreadPoolExecutor service1.setMaximumPoolSize(50); // 设置线程池中线程数的上限 // 2.执行指定线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象 service.execute(new NumberThread()); // 适用于Runnable service.execute(new NumberThread02()); // 适用于Runnable try { Future future = service.submit(new NumberThread03()); // 适用于Callable System.out.println("总和为:" + future.get()); } catch (Exception e) { e.printStackTrace(); } // 3.关闭连接池 service.shutdown(); } }在上述代码中,我们构建了一个线程池,并在 NumberThread03 类中通过实现 Callable 接口采用了 JDK 5.0 引入的一种新型线程创建方式。submit() 方法适用于通过 Callable 接口创建的线程。