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

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

为什么需要线程池

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

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

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

 

创建线程池的方式

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

1.newFixedThreadPool

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

代码示例如下:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class ExecutorTest extends Thread {
    private int index;
 
    public MyExecutor(int i) {
        this.index = i;
    }
 
    public void run() {
        try {
            System.out.println("[" + this.index + "] start....");
            Thread.sleep((int) (Math.random() * 10000));
            System.out.println("[" + this.index + "] end.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public static void main(String args[]) {
        ExecutorService service = Executors.newFixedThreadPool(4);
        for (int i = 0; i < 10; i++) {
            service.execute(new MyExecutor(i));
            // service.submit(new MyExecutor(i));
        }
        System.out.println("submit finish");
        service.shutdown();
    }
}

 

2.newCachedThreadPool

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

代码示例如下:

public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            final int j=i;
            executorService.submit(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+" "+j);
            });
        }
        System.out.println(executorService);
 
    }

 

3.newSingleThreadExecutor

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

代码示例如下:

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

 

4.newScheduledThreadPool

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

代码示例如下:

public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(int corePoolSize);

        scheduledExecutorService.schedule(new Runnable() {
            @Override
            public void run() {
                log.warn("schedule run");
            }
        }, 3, TimeUnit.SECONDS);
    }

 

 

5.newSingleThreadScheduledExecutor

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

代码示例如下:

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

输出:

pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
主程序退出了
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1

 

6.newWorkStealingPool

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

代码示例如下:

public static void main(final String[] arguments) throws InterruptedException {
    ExecutorService excr = Executors.newWorkStealingPool();
    ThreadPoolExecutor mypool = (ThreadPoolExecutor)  Executors.newCachedThreadPool();;
    System.out.println("size of mypool:" + mypool.getPoolSize());
    excr.submit(new Threadimpl());
    excr.submit(new Threadimpl());
    System.out.println("Total number threads scheduled):"+ mypool.getTaskCount());
    excr.shutdown();
 }  

 static class Threadimpl implements Runnable {

    public void run() {
       
       try {
          Long num = (long) (Math.random() / 30);
          System.out.println("Thread Name:" +Thread.currentThread().getName());
             TimeUnit.SECONDS.sleep(num);
          System.out.println("after sleep Thread Name:" +Thread.currentThread().getName());
       } catch (InterruptedException e) {
          e.printStackTrace();
       }
    }
 }

 

7.ThreadPoolExecutor

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

代码示例如下:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorDemo {

    private static final int CORE_POOL_SIZE = 5;
    private static final int MAX_POOL_SIZE = 10;
    private static final int QUEUE_CAPACITY = 100;
    private static final Long KEEP_ALIVE_TIME = 1L;
    public static void main(String[] args) {

        //使用阿里巴巴推荐的创建线程池的方式
        //通过ThreadPoolExecutor构造函数自定义参数创建
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 0; i < 10; i++) {
            //创建WorkerThread对象(WorkerThread类实现了Runnable 接口)
            Runnable worker = new MyRunnable("" + i);
            //执行Runnable
            executor.execute(worker);
        }
        //终止线程池
        executor.shutdown();
        while (!executor.isTerminated()) {
        }
        System.out.println("Finished all threads");
    }
}

 

 

作者简介

陈睿|mikechen,10年+大厂架构经验,BAT资深面试官,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

👇阅读更多mikechen架构文章👇

阿里架构 |双11秒杀 |分布式架构 |负载均衡 |单点登录 |微服务 |云原生 |高并发 |架构师

以上

关注作者「mikechen」公众号,获取更多技术干货!

后台回复架构,即可获取《阿里架构师进阶专题全部合集》,后台回复面试即可获取《史上最全阿里Java面试题总结

评论交流
    说说你的看法