当前位置: 首页 > article >正文

【Java 基础】22 多线程线程池

文章目录

    • 1.为什么使用线程池
    • 2.线程池有哪些种类
      • 1) 核心接口
      • 2)线程池分类
        • FixedThreadPool
        • CachedThreadPool
        • SingleThreadExecutor
        • ScheduledThreadPool
    • 总结

1.为什么使用线程池

使用多线程的开发中,频繁创建和销毁线程会带来较大的开销。我们可以使用线程池来有效的管理线程,它是一组预先创建的线程,可以重复使用,提高了线程的利用率,并且能够更好地控制线程的数量和执行方式。

2.线程池有哪些种类

1) 核心接口

线程池的主要接口是 ExecutorExecutorService

  • Executor 接口: 是线程池的根接口,只有一个 execute 方法用于执行任务

    public interface Executor {
        void execute(Runnable var1);
    }
    
  • ExecutorService 接口: 继承自 Executor,扩展了一些功能,如任务提交、任务执行、任务取消等

    public interface ExecutorService extends Executor {
        void shutdown()
        List<Runnable> shutdownNow()
        boolean isShutdown()
        boolean isTerminated()
        boolean awaitTermination()
        <T> Future<T> submit()
        Future<?> submit()
        <T> List<Future<T>> invokeAll()
        <T> T invokeAny()
    }
    

2)线程池分类

FixedThreadPool

固定大小的线程池,每个任务都被分配一个线程

示例代码:

public class Demo {
    public static void main(String[] args) {
        // 创建固定大小(3个)的线程池
        ExecutorService executor = Executors.newFixedThreadPool(3);
        // 提交5个任务
        for (int i = 0; i < 5; i++) {
            executor.execute(new RunnableDemo());
        }
        // 关闭线程池
        executor.shutdown();
    }
}

class RunnableDemo implements Runnable {
    @Override
    public void run() {
        String tName = Thread.currentThread().getName();
        System.out.println(tName + "正在执行...");
    }
}

输出结果:

pool-1-thread-1正在执行…
pool-1-thread-3正在执行…
pool-1-thread-3正在执行…
pool-1-thread-2正在执行…
pool-1-thread-1正在执行…

在这个例子中,创建了一个固定大小为3的线程池,提交了5个任务。线程池会根据任务数量和线程池大小来调度执行任务。通过 execute() 方法提交任务,线程池会自动选择线程执行任务。最后,调用 shutdown() 方法关闭线程池。

CachedThreadPool

可根据需要创建新线程的线程池,适用于执行很多短期异步任务的小程序

示例代码:

public class Demo {
    public static void main(String[] args) {
        // 创建 CachedThreadPool
        ExecutorService executor = Executors.newCachedThreadPool();
        // 提交任务
        for (int i = 0; i < 5; i++) {
            executor.execute(new RunnableDemo());
        }
        // 关闭线程池
        executor.shutdown();
    }
}

class RunnableDemo implements Runnable {
    @Override
    public void run() {
        String tName = Thread.currentThread().getName();
        System.out.println(tName + "正在执行...");
    }
}

输出结果:

pool-1-thread-1正在执行…
pool-1-thread-3正在执行…
pool-1-thread-2正在执行…
pool-1-thread-5正在执行…
pool-1-thread-4正在执行…

在这个例子中,Executors.newCachedThreadPool() 创建了一个 CachedThreadPool,并提交了5个任务给线程池执行。由于 CachedThreadPool 的特性,线程池会根据需要动态创建新线程,并在一段时间内保留空闲线程以备复用。在这个例子中,任务数量较少,因此线程池可能会重用现有线程,也可能会创建新线程。最后,调用 shutdown() 方法关闭线程池。

SingleThreadExecutor

单线程的线程池,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行

示例代码:

public class Demo {
    public static void main(String[] args) {
        // 创建 SingleThreadExecutor
        ExecutorService executor = Executors.newSingleThreadExecutor();
        // 提交任务
        for (int i = 0; i < 5; i++) {
            executor.execute(new RunnableDemo());
        }
        // 关闭线程池
        executor.shutdown();
    }
}

class RunnableDemo implements Runnable {
    @Override
    public void run() {
        String tName = Thread.currentThread().getName();
        System.out.println(tName + "正在执行...");
    }
}

输出结果:

pool-1-thread-1正在执行…
pool-1-thread-1正在执行…
pool-1-thread-1正在执行…
pool-1-thread-1正在执行…
pool-1-thread-1正在执行…

在这个例子中,Executors.newSingleThreadExecutor() 创建了一个 SingleThreadExecutor,并提交了5个任务给线程池执行。由于 SingleThreadExecutor 的特性,所有任务会按照提交的顺序在同一个线程中执行。即使有多个任务并发提交,线程池也会保证这些任务一个接一个地执行。最后调用 shutdown() 方法关闭线程池。

ScheduledThreadPool

定时任务线程池,用于定时执行任务

示例代码:

public class Demo {
    public static void main(String[] args) {
        // 创建 ScheduledThreadPool
        ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(3);
        // 延迟任务
        scheduledExecutor.schedule(new RunnableDemo(), 2, TimeUnit.SECONDS);
        // 周期性任务,每隔一秒执行一次
        scheduledExecutor.scheduleAtFixedRate(new RunnableDemo(), 0, 1, TimeUnit.SECONDS);
        // 周期性任务,任务执行完成后延迟一秒再执行下一次
        scheduledExecutor.scheduleWithFixedDelay(new RunnableDemo(), 0, 1, TimeUnit.SECONDS);
        // 主线程等待一段时间,观察任务的执行
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 关闭线程池
        scheduledExecutor.shutdown();
    }
}

class RunnableDemo implements Runnable {
    @Override
    public void run() {
        String tName = Thread.currentThread().getName();
        System.out.println(tName + "正在执行...");
    }
}

输出结果:

pool-1-thread-1正在执行…
pool-1-thread-3正在执行…
pool-1-thread-1正在执行…
pool-1-thread-2正在执行…
pool-1-thread-3正在执行…
pool-1-thread-3正在执行…
pool-1-thread-3正在执行…
pool-1-thread-3正在执行…
pool-1-thread-3正在执行…
pool-1-thread-2正在执行…
pool-1-thread-1正在执行…
pool-1-thread-3正在执行…
pool-1-thread-3正在执行…
pool-1-thread-1正在执行…
pool-1-thread-2正在执行…
pool-1-thread-3正在执行…
pool-1-thread-1正在执行…
pool-1-thread-2正在执行…
pool-1-thread-3正在执行…
pool-1-thread-1正在执行…
pool-1-thread-2正在执行…

在这个例子中,Executors.newScheduledThreadPool(3) 创建了一个大小为3的 ScheduledThreadPool。通过 schedule 方法可以延迟执行任务,通过 scheduleAtFixedRatescheduleWithFixedDelay 方法可以执行周期性任务。最后通过 shutdown 方法关闭线程池。在主线程等待一段时间后,可以观察到任务的执行情况。

总结

使用线程池是编写高效多线程程序的一种重要方式。它能够降低线程创建和销毁的开销,更好地管理线程的数量,提高系统的性能和响应速度。在选择线程池时,需要根据具体的需求和场景选择合适的线程池类型。


http://www.kler.cn/a/160389.html

相关文章:

  • SQL面试题——奔驰SQL面试题 车辆在不同驾驶模式下的时间
  • C++中string的新特性
  • 传奇996_21——龙岭事件
  • 第一个 Flutter 项目(1)共46节
  • 容器技术在DevOps中的应用
  • MybatisPlus入门(十)MybatisPlus-逻辑删除和多记录操作
  • 2022年第十一届数学建模国际赛小美赛A题翼龙如何飞行解题全过程文档及程序
  • 在github中通过action自动化部署 hugo academic theme,实现上传md文件更新博客内容
  • 华为数通---配置端口安全案例
  • 解决el-tree数据回显时子节点部分选中父节点都全选中问题
  • NFC和蓝牙在物联网中有什么意义?如何选择?
  • 华为设备使用python配置netconf 功能
  • javaee实验:文件上传及拦截器的使用
  • HarmonyOS4.0从零开始的开发教程03初识ArkTS开发语言(中)
  • RPC简介和grpc的使用
  • MySQL 添加注释(comment)
  • 二叉平衡树
  • CoDeF视频处理——视频风格转化部署使用与源码解析
  • 《Java 并发编程艺术》笔记(上)
  • 处理实时视频流:第三方美颜SDK的实时图像处理策略
  • idea开发环境配置
  • C++11改进观察者模式
  • js 将后端返回的对象转换为数组
  • VUEX使用总结
  • spark log4j日志配置
  • Amazon CodeWhisperer 正式可用, 并面向个人开发者免费开放