博客
关于我
并发--线程池--Executors
阅读量:505 次
发布时间:2019-03-07

本文共 6015 字,大约阅读时间需要 20 分钟。

Java 线程池常见种类与使用方法

随着现代应用程序对并发处理要求的不断提高,Java 的线程池机制成为开发者的利手工具。本文将介绍 Java 线程池的几种常见种类及其使用方法,帮助开发者更好地理解线程池的特性和适用场景。

一、线程池的简介

线程池是一种资源管理的机制,它允许程序高效地配置和使用多个线程来执行任务。通过线程池,开发者无需手动管理线程的生命周期,而是通过任务提交的方式,线程池会根据需求自动创建、管理和终止线程。常见的线程池种类包括 固定大小单个定时缓存

二、线程池的创建方法

1. 固定大小线程池

使用 Executors.newFixedThreadPool(int nThreads) 创建固定大小的线程池。

ExecutorService executor = Executors.newFixedThreadPool(3);
  • 特点:线程池中始终保持指定数量的核心线程(corePoolSize)。当线程数量达到最大值后,新任务会被 enqueue至队列中,直到核心线程空闲。
// 创建固定大小线程池ExecutorService executor = Executors.newFixedThreadPool(3);// 提交任务for (int i = 0; i < 6; i++) {    executor.execute(new MyTask(i));}executor.shutdown();

2. 单个线程池

使用 Executors.newSingleThreadExecutor() 创建单线程池。

ExecutorService executor = Executors.newSingleThreadExecutor();
  • 特点:只创建一个核心线程处理所有任务,任务按提交顺序串行执行。
  • 优点:任务执行顺序明确,不会出现任务乱序。
  • 缺点:如果线程被异常终止,会重新创建线程继续任务执行。
// 创建单线程定时池ExecutorService executor = Executors.newSingleThreadScheduledExecutor();// 定期执行任务executor.scheduleAtFixedDelay(new Runnable(), 0, 5, TimeUnit.SECONDS);

3. 定时线程池

  • 如果需要周期性执行任务,可以使用 ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
  • 适用于任务需要在特定时间间隔后执行的情况。

4. 缓存线程池

使用 ThreadPoolExecutor 的构造方法直接指定 corePoolSizemaxPoolSize

new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue<>());
  • 特点:支持动态创建和回收线程,适用于任务负载波动较大的场景。
// 创建缓存线程池ExecutorService executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue<>());

三、固定大小线程池的工作流程

固定大小线程池使用无界队列(LinkedBlockingQueue)作为工作队列,其核心特点包括:

  • 当核心线程未满时:立即创建新的核心线程执行任务。
  • 当核心线程已满时:将新的任务 enqueu到队列中,等待核心线程空闲。
  • 任务从队列中获取:核心线程会一直从队列中获取任务执行,直到队列为空。
  • 示例代码

    class MyTask implements Runnable {    private int taskNum;    public MyTask(int num) {        this.taskNum = num;    }    @Override    public void run() {        System.out.println("Thread " + Thread.currentThread().getName() + "正在执行任务 " + taskNum);        try {            Thread.sleep(1000); // 模拟耗时任务        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("Thread " + Thread.currentThread().getName() + "完成执行任务 " + taskNum);    }}public class Demo {    public static void main(String[] args) {        ExecutorService executor = Executors.newFixedThreadPool(3); // 创建3个核心线程        for (int i = 0; i < 6; i++) {            executor.execute(new MyTask(i));        }        executor.shutdown();    }}

    运行结果说明:

    • 线程池初始创建3个核心线程。
    • 新任务被 enqueu至队列,核心线程逐一处理。
    • 每个任务执行完成后会Log结果。

    四、单个线程池的工作流程

    单个线程池与固定大小线程池的区别主要在于:

    • 只有一个核心线程处理所有任务。
    • 任务会按顺序执行,缺少并行性。

    示例代码

    class MyTask implements Runnable {    private int taskNum;    public MyTask(int num) {        this.taskNum = num;    }    @Override    public void run() {        System.out.println("Thread " + Thread.currentThread().getName() + "正在执行任务 " + taskNum);        try {            Thread.sleep(1000); // 模拟耗时任务        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("Thread " + Thread.currentThread().getName() + "完成执行任务 " + taskNum);    }}public class Demo {    public static void main(String[] args) {        ExecutorService executor = Executors.newSingleThreadExecutor();        for (int i = 0; i < 6; i++) {            executor.execute(new MyTask(i));        }        executor.shutdown();    }}

    运行结果说明:

    • 只有一个线程负责执行所有任务。
    • 任务按顺序依次处理,结果输出也是按照任务提交顺序出现。

    五、定时线程池的应用场景

    定时线程池适合需要在特定时间间隔触发任务执行的情景。例如发送定时邮件、定期检查系统状态等。

    使用方法

    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();executor.scheduleWithFixedDelay(new Runnable(), initialDelay, delay, TimeUnit.SECONDS);

    其中 initialDelay 表示第一次执行的延迟,delay 表示后续任务的固定执行间隔。

    示例代码

    import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;class MyTask implements Runnable {    private int taskNum;    public MyTask(int num) {        this.taskNum = num;    }    @Override    public void run() {        try {            System.out.println("Thread " + Thread.currentThread().getName() + "正在执行任务 " + taskNum);            Thread.sleep(1000); // 模拟耗时任务        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("Thread " + Thread.currentThread().getName() + "完成执行任务 " + taskNum);    }}public class Demo {    public static void main(String[] args) {        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();        executor.scheduleWithFixedDelay(new MyTask(), 0, 3, TimeUnit.SECONDS); // 每隔3秒执行一次        executor.shutdown();    }}

    运行结果说明:

    • 每隔3秒,线程池中创建一个新任务,按照预定的间隔执行任务。
    • 如果任务执行耗时较长,任务调度也会继续,第二个任务将在第4秒开始执行。

    六、缓存线程池的优势

    缓存线程池的核心特点是支持动态创建和回收线程,适合任务负载波动较大的场景。其最大池大小为 Integer.MAX_VALUE,超出核心线程数的空闲线程会在60秒内若无新任务提交则终止。

    使用方法

    ThreadPoolExecutor executor = new ThreadPoolExecutor(    0,     Integer.MAX_VALUE,     60,     TimeUnit.SECONDS,     new SynchronousQueue<>());

    示例代码

    import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;class MyTask implements Runnable {    private int taskNum;    public MyTask(int num) {        this.taskNum = num;    }    @Override    public void run() {        System.out.println("Thread " + Thread.currentThread().getName() + "正在执行任务 " + taskNum);        try {            Thread.sleep(1000); // 模拟耗时任务        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("Thread " + Thread.currentThread().getName() + "完成执行任务 " + taskNum);    }}public class Demo {    public static void main(String[] args) {        ThreadPoolExecutor executor = new ThreadPoolExecutor(            0, // corePoolSize            Integer.MAX_VALUE, // maximumPoolSize            60, // keepAliveTime            TimeUnit.SECONDS, // time unit            new SynchronousQueue<>() // work queue        );        for (int i = 0; i < 10; i++) {            executor.execute(new MyTask(i));        }        executor.shutdown();    }}

    运行结果说明:

    • 缓存线程池根据任务需求自动扩展和收缩线程数量,能最大化资源利用率。
    • 空闲线程将在60秒内若无新任务则终止,避免资源浪费。

    总结

    线程池是Java中处理并发任务的重要工具,其中固定大小、单个、定时和缓存线程池各有特点。选择合适的线程池类型,能够有效地优化程序性能和资源利用率。在实际开发中,根据任务的特性和负载情况,合理使用线程池,使程序更加高效和健壮。

    转载地址:http://futjz.baihongyu.com/

    你可能感兴趣的文章
    php实现图片背景换色功能
    查看>>
    php实现多个一维数组对应合并成二维数组
    查看>>
    php实现多关键字查找方法
    查看>>
    PHP实现微信公众号H5支付
    查看>>
    PHP实现微信公众号网页授权
    查看>>
    PHP实现微信小程序推送消息至公众号
    查看>>
    rabbitmq逻辑与开发
    查看>>
    php实现根据身份证获取年龄
    查看>>
    PHP实现的MongoDB数据增删改查
    查看>>
    PHP实现的SSO单点登录系统,拿走就用吧
    查看>>
    php实现短信验证功能
    查看>>
    RabbitMQ连接报错(1)—— None of the specified endpoints were reachable
    查看>>
    php实现逆转数组
    查看>>
    PHP实现通过geoip获取IP地理信息
    查看>>
    PHP实现页面静态化、纯静态化及伪静态化
    查看>>
    php容许ajax跨域,PHP设置允许ajax跨域请求的两种常见方法
    查看>>
    RabbitMQ进程结构分析与性能调优
    查看>>
    PHP对接百度地图
    查看>>
    PHP对表单提交特殊字符的过滤和处理
    查看>>
    php对象引用和析构函数的关系
    查看>>