为什么需要线程池
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");
- }
- }