java基础-多线程(8)

78 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天

线程池

介绍

Java语言虽然内置了多线程支持,启动一个新线程非常方便,但是,创建线程需要操作系统资源(线程资源,栈空间等),频繁创建和销毁大量线程需要消耗大量时间。

如果可以复用一组线程:

image-20221005235037018

那么我们就可以把很多小任务让一组线程来执行,而不是一个任务对应一个新线程。这种能接收大量小任务并进行分发处理的就是线程池。

简单地说,线程池内部维护了若干个线程,没有任务的时候,这些线程都处于等待状态。如果有新任务,就分配一个空闲线程执行。如果所有线程都处于忙碌状态,新任务要么放入队列等待,要么增加一个新线程进行处理。

Java标准库提供了ExecutorService接口表示线程池,它的典型用法如下:

 // 创建固定大小的线程池:
 ExecutorService executor = Executors.newFixedThreadPool(3);
 // 提交任务:
 executor.submit(task1);
 executor.submit(task2);
 executor.submit(task3);
 executor.submit(task4);
 executor.submit(task5);

使用线程池

  • 背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能景响很大。

  • 思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。

  • 好处:

    • 提高响应速度(减少了创建新线程的时间)

    • 降低资源消耗(重复利用线程池中线程,不需要每次都创建)

    • 便于线程管理()

      • corePoolSize:核心池的大小
      • maximumPoolSize:最大线程数
      • keepAliveTime:线程没有任务时最多保持多长时间后会终止
  • JDK 5.0起提供了线程池相关API: ExecutorService 和Executors

  • ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor

    • void execute(Runnable command) :执行任务/命令,没有返回值,一般用来执行Runnable
    • Future submit(Callable task):执行任务,有返回值,一般又来执行Callable
    • void shutdown() :关闭连接池
  • Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池

 //测试线程池
 public class Demo35_ThreadPool {
     public static void main(String[] args) {
         // 1. 创建服务,擦行间线程池
         // newFixedThreadPool(线程池大小)
         ExecutorService service = Executors.newFixedThreadPool(10);
         //执行
         service.execute(new MyThread());
         service.execute(new MyThread());
         service.execute(new MyThread());
         service.execute(new MyThread());
         service.execute(new MyThread());
         service.execute(new MyThread());
         //关闭连接
         service.shutdown();
     }
 }
 ​
 class MyThread implements Runnable {
     @Override
     public void run() {
         System.out.println(Thread.currentThread().getName());
     }
 }
 ​

总结

了解线程池,可能更好了解多线程的底层知识结构体系。