前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【面试必会】线程池创建方式详解

【面试必会】线程池创建方式详解

原创
作者头像
祁画
发布2024-08-02 18:04:47
790
发布2024-08-02 18:04:47
举报
文章被收录于专栏:技术分享

最近面试问道了线程池的创建方式,这里出一篇文章记录下这一知识点!

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的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 会停止该任务的后续执行,但不会停止线程池本身或其他任务的执行。如果需要处理任务执行中的异常,可以在任务内部进行捕获和处理。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • FixedThreadPool
  • CachedThreadPool
  • SingleThreadExecutor
  • ScheduledThreadPool
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档