关于几种线程池,简单聊下

652 阅读4分钟

线程池(百度百科)

线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池 维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量

Java中的线程池种类

1.单线程的线程池 newSingleThreadExecutor 单线程线程池只有一个线程工作串行执行所有工作

代码示例

 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 public class pool {
 public static void main(String[] args) {
    ExecutorService  pool = Executors.newSingleThreadExecutor();
    for (int i = 0; i < 5; i++) {
        pool.execute(() -> {
            System.out.println("Hello World"+" "+"我是线程"+Thread.currentThread().getName() );
        });
    }
 }
 }

运行结果:从运行结果来看 只有一个线程在运行

 Hello World 我是线程pool-1-thread-1
 Hello World 我是线程pool-1-thread-1
 Hello World 我是线程pool-1-thread-1
 Hello World 我是线程pool-1-thread-1
 Hello World 我是线程pool-1-thread-1

2.固定大小的线程池 newFixedThreadPool 就像一个固定的容器,每次提交一个任务就去创建一个线程去执行,直到达到线程池的最大大小,线程池的大小达到最大值后就不会变

代码示例 首先创建一个大小为5的线程池 执行5个任务

 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 public class pool {
 public static void main(String[] args) {
     ExecutorService  pool = Executors.newFixedThreadPool(5);
     for (int i = 0; i < 5; i++) {
        pool.execute(() -> {
            System.out.println("Hello World"+" "+"我是线程"+Thread.currentThread().getName() );
        });
    }
  }
 }

运行结果:可以看到一直达到线程池的最大大小

 Hello World 我是线程pool-1-thread-2
 Hello World 我是线程pool-1-thread-1
 Hello World 我是线程pool-1-thread-5
 Hello World 我是线程pool-1-thread-4
 Hello World 我是线程pool-1-thread-3

接下来我们放10个任务进去

      for (int i = 0; i < 10; i++) {
        pool.execute(() -> {
            System.out.println("Hello World"+" "+"我是线程"+Thread.currentThread().getName() );
        });
    }

结果:可以看到线程池达到最大容量后 随机分配线程去执行了任务

 Hello World 我是线程pool-1-thread-3
 Hello World 我是线程pool-1-thread-1
 Hello World 我是线程pool-1-thread-3
 Hello World 我是线程pool-1-thread-1
 Hello World 我是线程pool-1-thread-3
 Hello World 我是线程pool-1-thread-1
 Hello World 我是线程pool-1-thread-5
 Hello World 我是线程pool-1-thread-4
 Hello World 我是线程pool-1-thread-2

3.定时及可以周期性执行任务的线程池newScheduledThreadPool,此线程池也有固定的大小,但是执行任务的时候并不是一直执行任务,直到线程池的最大大小

代码示例:创建一个大小为5的线程,执行10个任务,并且3秒后执行

 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 public class pool {
 public static void main(String[] args) {
    ExecutorService  pool = Executors.newScheduledThreadPool(5);
    for (int i = 0; i < 10; i++) {
        ((ScheduledExecutorService) pool).schedule(() -> {
            System.out.println("Hello World"+" "+"我是线程"+Thread.currentThread().getName() );
        },3,TimeUnit.SECONDS);
    }
  }
 }

结果:可以看到在3秒后线程池开始执行任务,并且也是随机分配线程去执行任务

 Hello World 我是线程pool-1-thread-2
 Hello World 我是线程pool-1-thread-2
 Hello World 我是线程pool-1-thread-2
 Hello World 我是线程pool-1-thread-2
 Hello World 我是线程pool-1-thread-2
 Hello World 我是线程pool-1-thread-2
 Hello World 我是线程pool-1-thread-2
 Hello World 我是线程pool-1-thread-5
 Hello World 我是线程pool-1-thread-1

4.可缓存的线程池 newCachedThreadPool 可以看做是一个可变大小的线程池,当线程池的大小超过需要执行任务的数量时,会回收部分线程,而当任务数量增加时,又会增加新的线程去执行任务。

代码示例:创建线程池去执行5个任务

 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 public class pool {
 public static void main(String[] args) {
    ExecutorService  pool = Executors.newCachedThreadPool();
    for (int i = 0; i < 5; i++) {
        pool.execute(() -> {
            System.out.println("Hello World"+" "+"我是线程"+Thread.currentThread().getName() );
        });
    }
  }
 }

结果

 Hello World 我是线程pool-1-thread-3
 Hello World 我是线程pool-1-thread-2
 Hello World 我是线程pool-1-thread-1
 Hello World 我是线程pool-1-thread-5
 Hello World 我是线程pool-1-thread-4

当我们放10个任务进去的时候

执行结果

 Hello World 我是线程pool-1-thread-1
 Hello World 我是线程pool-1-thread-5
 Hello World 我是线程pool-1-thread-2
 Hello World 我是线程pool-1-thread-6
 Hello World 我是线程pool-1-thread-4
 Hello World 我是线程pool-1-thread-8
 Hello World 我是线程pool-1-thread-9
 Hello World 我是线程pool-1-thread-10
 Hello World 我是线程pool-1-thread-3
 Hello World 我是线程pool-1-thread-7

源码分析:可以看到线程池的初始大小为0,但允许线程池数量为最大

  public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}