为什么推荐使用线程池

128 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情

启动1个线程

刚开始学习线程的时候,对于可以异步处理的任务,直接创建一个新的线程来处理。任务少没有什么问题。如代码所示:

public class ThreadTask {
    public static void main(String[] arg){
      Thread th = new Thread(new Task());
      th.start();
    }
    static class Task implements Runnable { 
        public void run() { 
           System.out.println("Thread Name: " + Thread.currentThread().getName());
        } 

    } 

}

根据以上代码,发布一个任务并将其放入子线程中,然后启动子线程执行任务。整个过程很简单,执行结果就会打印出 “Thread Name:Thread-0”,即当前线程默认的名字。

但是随着任务增多的时候,比如可能有10个任务建立起10个子线程进行处理:

for (int i = 0; i < 10; i++) { 
            Thread thread = new Thread(new Task());
            thread.start();
} 

打印结果你会发现顺序是无序的,不是按顺序打印出来。主要原因是运行的顺序取决于线程调度器所以会导致随机产生。

启动10000个线程

如果我们将子线程创建10000个,每个人任务都需要一定的耗时,那肯定产生很大的系统开销和资源浪费。

  • 创建和销毁都需要时间,10000多个子线程反复创建销毁都会导致系统开销增大
  • 占用内存和资源过多,太多线程占用,且它们线程切换也会导致系统不问题。

线程池

线程池就是来解决以上两个问题。线程池设置固定的线程数据量来保持工作状态并反复执行任务,这样就可以解决线程的创建开销问题。就是说,存在一些线程会一直在执行任务,一个任务执行完后再继续执行下一个任务,就完全不用担心每次都要创建一个线程才能执行任务。

同时,只需要设置固定的线程数来保持一直工作状态,就不用但是太多的线程占用太多的内存资源的问题。

线程池设计思路

线程池的设计思路就像是一个池子,有固定的管道,然后往管道里注入水到池子里。一吨水通过一个管道注入水完后,这个管道还可以继续用来注入水到池子里。

所以,需要固定的线程数保持工作状态,也保证资源不会被过度消耗。

public static void main(String[] args) { 
        ExecutorService service = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10000; i++) { 
            service.execute(new Task());
        } 
    System.out.println(Thread.currentThread().getName());

    } 

从以上代码上看,创建了一个有5个线程的线程池,然后将10000个任务都放入到线程池里执行。从输出结果就可以看出一直都是这5个线程在反复的执行任务。

线程池优势

  • 解决线程创建和销毁导致的系统开销问题。因为固定数量的线程可以反复使用,减小开销也能提升响应速度
  • 避免资源使用不当。线程池根据配置和任务数量灵活控制线程数量,避免创建过多或过少的线程
  • 线程池统一管理线程,方便使用。