创建线程池的几种方式(7种常见方式详解)

创建线程池的几种方式(7种常见方式详解)-mikechen

为什么需要线程池

创建线程池的几种方式(7种常见方式详解)-mikechen

java中为了提高并发度,可以使用多线程共同执行,但是如果有大量线程短时间之内被创建和销毁,会占用大量的系统时间,影响系统效率。

为了解决上面的问题,java中引入了线程池,可以使创建好的线程在指定的时间内由系统统一管理,而不是在执行时创建,执行后就销毁,从而避免了频繁创建、销毁线程带来的系统开销。

 

创建线程池的方式

创建线程池的方式有 7 种:

1.newFixedThreadPool

创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。

代码示例如下:

  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. public class ExecutorTest extends Thread {
  4. private int index;
  5. public MyExecutor(int i) {
  6. this.index = i;
  7. }
  8. public void run() {
  9. try {
  10. System.out.println("[" + this.index + "] start....");
  11. Thread.sleep((int) (Math.random() * 10000));
  12. System.out.println("[" + this.index + "] end.");
  13. } catch (Exception e) {
  14. e.printStackTrace();
  15. }
  16. }
  17. public static void main(String args[]) {
  18. ExecutorService service = Executors.newFixedThreadPool(4);
  19. for (int i = 0; i < 10; i++) {
  20. service.execute(new MyExecutor(i));
  21. // service.submit(new MyExecutor(i));
  22. }
  23. System.out.println("submit finish");
  24. service.shutdown();
  25. }
  26. }

 

2.newCachedThreadPool

创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。

代码示例如下:

  1. public static void main(String[] args) {
  2. ExecutorService executorService = Executors.newCachedThreadPool();
  3. for (int i = 0; i < 5; i++) {
  4. final int j=i;
  5. executorService.submit(()->{
  6. try {
  7. TimeUnit.MILLISECONDS.sleep(50);
  8. } catch (InterruptedException e) {
  9. e.printStackTrace();
  10. }
  11. System.out.println(Thread.currentThread().getName()+" "+j);
  12. });
  13. }
  14. System.out.println(executorService);
  15. }

 

3.newSingleThreadExecutor

创建单个线程数的线程池,它可以保证先进先出的执行顺序。

代码示例如下:

  1. public static void main(String[] args) {
  2. ExecutorService executorService = Executors.newSingleThreadExecutor();
  3. for (int i = 0; i < 6; i++) {
  4. final int j=i;
  5. executorService.execute(()->{
  6. System.out.println(Thread.currentThread().getName()+" "+j);
  7. });
  8. }
  9. executorService.shutdown();
  10. }

 

4.newScheduledThreadPool

创建一个可以执行延迟任务的线程池,延迟执行。

代码示例如下:

  1. public static void main(String[] args) {
  2. ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(int corePoolSize);
  3.  
  4. scheduledExecutorService.schedule(new Runnable() {
  5. @Override
  6. public void run() {
  7. log.warn("schedule run");
  8. }
  9. }, 3, TimeUnit.SECONDS);
  10. }

 

 

5.newSingleThreadScheduledExecutor

创建一个单线程的可以执行延迟任务的线程池。

代码示例如下:

  1. public static void main(String[] args) throws Exception {
  2. ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
  3. // 1秒打印一次 当前线程名
  4. service.scheduleAtFixedRate(() -> System.out.println(Thread.currentThread().getName()), 1, 1, TimeUnit.SECONDS);
  5. // 主线程等待10秒
  6. TimeUnit.SECONDS.sleep(10);
  7. System.out.println("主线程退出了");
  8. }

输出:

  1. pool-1-thread-1
  2. pool-1-thread-1
  3. pool-1-thread-1
  4. pool-1-thread-1
  5. pool-1-thread-1
  6. pool-1-thread-1
  7. pool-1-thread-1
  8. pool-1-thread-1
  9. pool-1-thread-1
  10. 主程序退出了
  11. pool-1-thread-1
  12. pool-1-thread-1
  13. pool-1-thread-1
  14. pool-1-thread-1
  15. pool-1-thread-1
  16. pool-1-thread-1

 

6.newWorkStealingPool

创建一个抢占式执行的线程池(任务执行顺序不确定)【JDK 1.8 添加】。

代码示例如下:

  1. public static void main(final String[] arguments) throws InterruptedException {
  2. ExecutorService excr = Executors.newWorkStealingPool();
  3. ThreadPoolExecutor mypool = (ThreadPoolExecutor) Executors.newCachedThreadPool();;
  4. System.out.println("size of mypool:" + mypool.getPoolSize());
  5. excr.submit(new Threadimpl());
  6. excr.submit(new Threadimpl());
  7. System.out.println("Total number threads scheduled):"+ mypool.getTaskCount());
  8. excr.shutdown();
  9. }
  10.  
  11. static class Threadimpl implements Runnable {
  12.  
  13. public void run() {
  14. try {
  15. Long num = (long) (Math.random() / 30);
  16. System.out.println("Thread Name:" +Thread.currentThread().getName());
  17. TimeUnit.SECONDS.sleep(num);
  18. System.out.println("after sleep Thread Name:" +Thread.currentThread().getName());
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. }

 

7.ThreadPoolExecutor

最原始的创建线程池的方式,它包含了 7 个参数可供设置。

代码示例如下:

  1. import java.util.concurrent.ArrayBlockingQueue;
  2. import java.util.concurrent.ThreadPoolExecutor;
  3. import java.util.concurrent.TimeUnit;
  4.  
  5. public class ThreadPoolExecutorDemo {
  6.  
  7. private static final int CORE_POOL_SIZE = 5;
  8. private static final int MAX_POOL_SIZE = 10;
  9. private static final int QUEUE_CAPACITY = 100;
  10. private static final Long KEEP_ALIVE_TIME = 1L;
  11. public static void main(String[] args) {
  12.  
  13. //使用阿里巴巴推荐的创建线程池的方式
  14. //通过ThreadPoolExecutor构造函数自定义参数创建
  15. ThreadPoolExecutor executor = new ThreadPoolExecutor(
  16. CORE_POOL_SIZE,
  17. MAX_POOL_SIZE,
  18. KEEP_ALIVE_TIME,
  19. TimeUnit.SECONDS,
  20. new ArrayBlockingQueue<>(QUEUE_CAPACITY),
  21. new ThreadPoolExecutor.CallerRunsPolicy());
  22.  
  23. for (int i = 0; i < 10; i++) {
  24. //创建WorkerThread对象(WorkerThread类实现了Runnable 接口)
  25. Runnable worker = new MyRunnable("" + i);
  26. //执行Runnable
  27. executor.execute(worker);
  28. }
  29. //终止线程池
  30. executor.shutdown();
  31. while (!executor.isTerminated()) {
  32. }
  33. System.out.println("Finished all threads");
  34. }
  35. }

 

 

评论交流
    说说你的看法
欢迎您,新朋友,感谢参与互动!