10.线程池

感谢秦疆老师的JUC并发编程视频,更多了解哔哩哔哩搜索【狂神说Java】。

本文内容源于秦疆老师的JUC并发编程视频教程。给狂神推荐,点赞吧!

线程池

线程池:三大方法、7大参数、4种拒绝策略

池化技术

程序的运行,本质:占用系统的资源!优化资源的使用!=》池化技术

线程池、连接池、内存池、对象池//

池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。

线程池的好处:

  1. 降低资源的消耗
  2. 提高响应的速度
  3. 方便管理

线程复用,可以控制最大并发数,管理线程

线程池:三大方法

阿里巴巴开发手册规范:

在这里插入图片描述
代码测试:

package demo7;


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//Executors 工具类 3大方法
public class ExecutorsTest1 {

    public static void main(String[] args) {

        ExecutorService executorService = null;
        //单一线程
        executorService = Executors.newSingleThreadExecutor();
        //创建一个固定的线程池的大小
         Executors.newFixedThreadPool(5);
        //创建可伸缩的,遇强则强,遇弱则弱
         Executors.newCachedThreadPool();
        try {
            for (int i = 0; i < 10; i++) {
                //使用线程池之后,使用线程池来创建线程
                executorService.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " =>ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //线程池用完,程序结束,关闭线程池
            executorService.shutdown();
        }


    }
}
  1. Executors.newSingleThreadExecutor()
//单一线程
ExecutorService executorService = Executors.newSingleThreadExecutor();

输出:

pool-1-thread-1 =>ok
pool-1-thread-1 =>ok
pool-1-thread-1 =>ok
pool-1-thread-1 =>ok
pool-1-thread-1 =>ok
pool-1-thread-1 =>ok
pool-1-thread-1 =>ok
pool-1-thread-1 =>ok
pool-1-thread-1 =>ok
pool-1-thread-1 =>ok
  1. Executors.newFixedThreadPool(5)
//创建一个固定的线程池的大小
ExecutorService executorService = Executors.newFixedThreadPool(5);

输出:

pool-1-thread-1 =>ok
pool-1-thread-2 =>ok
pool-1-thread-1 =>ok
pool-1-thread-2 =>ok
pool-1-thread-2 =>ok
pool-1-thread-2 =>ok
pool-1-thread-4 =>ok
pool-1-thread-5 =>ok
pool-1-thread-1 =>ok
pool-1-thread-3 =>ok
  1. Executors.newCachedThreadPool()
//创建可伸缩的,遇强则强,遇弱则弱
ExecutorService executorService = Executors.newCachedThreadPool();

输出:

pool-1-thread-2 =>ok
pool-1-thread-5 =>ok
pool-1-thread-4 =>ok
pool-1-thread-3 =>ok
pool-1-thread-1 =>ok
pool-1-thread-6 =>ok
pool-1-thread-6 =>ok
pool-1-thread-7 =>ok
pool-1-thread-8 =>ok
pool-1-thread-9 =>ok

七大参数

七大参数

  • int corePoolSize, //核心线程池大小
  • int maximumPoolSize, //最大核心线程池大小
  • long keepAliveTime, //超时了没有人调用就会释放
  • TimeUnit unit, //超时单位
  • BlockingQueue workQueue, //阻塞队列
  • ThreadFactory threadFactory, //线程工厂:创建线程的,一般不用动
  • RejectedExecutionHandler handler //拒绝策略

源码分析:

//核心线程数,最大线程数都为 1
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}



// nThreads, nThreads, =>newFixedThreadPool(5)  把核心线程数,最大线程数这两个参数都变成5 
  public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }


//0, Integer.MAX_VALUE 约等于21亿 OOM
  public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }


//本质ThreadPoolExecutor()


  public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
                              int maximumPoolSize,//最大核心线程池大小
                              long keepAliveTime,//超时了没有人调用就会释放
                              TimeUnit unit,//超时单位
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }



//this()
 public ThreadPoolExecutor(int corePoolSize,//核心线程池大小
                              int maximumPoolSize,//最大核心线程池大小
                              long keepAliveTime,//超时了没有人调用就会释放
                              TimeUnit unit,//超时单位
                              BlockingQueue<Runnable> workQueue,//阻塞队列
                              ThreadFactory threadFactory,//线程工厂:创建线程的,一般不用动
                              RejectedExecutionHandler handler//拒绝策略
                          ) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }


自定义线程池

阿里巴巴手册规范:

在这里插入图片描述

在这里插入图片描述

手动创建线程池

package demo7;

import java.util.concurrent.*;

/**
 * 手动创建线程池
 * <p>
 * int corePoolSize,
 * int maximumPoolSize,
 * long keepAliveTime,
 * TimeUnit unit,
 * BlockingQueue<Runnable> workQueue,
 * ThreadFactory threadFactory,
 * RejectedExecutionHandler handler
 */
public class ExecutorsTest2 {

    public static void main(String[] args) {

        //自定义线程池
        ExecutorService executorService = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                // new ThreadPoolExecutor.AbortPolicy() //默认 银行满了,还有人进来,不处理这个人,抛出异常
                // new ThreadPoolExecutor.DiscardOldestPolicy()//队列满了, 丢掉任务 ,不会抛出异常
                // new ThreadPoolExecutor.CallerRunsPolicy()//哪来的哪去
                new ThreadPoolExecutor.DiscardOldestPolicy()//队列满了,尝试和最早的竞争,不会抛出异常
        );


        try {
            //最大承载 = 队列 deque + max
            //超出抛出RejectedExecutionException 异常
            for (int i = 1; i <= 10; i++) {
                executorService.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "=>ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭线程池
            executorService.shutdown();
        }


    }
}

4种拒绝策略

4种拒绝策略

  • new ThreadPoolExecutor.AbortPolicy() //默认的策略 银行满了,还有人进来,不处理这个人,抛出异常

在这里插入图片描述

  • new ThreadPoolExecutor.CallerRunsPolicy() //哪来的哪去

在这里插入图片描述

  • new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了, 丢掉任务 ,不会抛出异常
    在这里插入图片描述

  • new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试和最早的竞争,不会抛出异常
    在这里插入图片描述
    源码:

//由调用线程(提交任务的线程)处理该任务
public static class CallerRunsPolicy implements RejectedExecutionHandler {

    public CallerRunsPolicy() { }


    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}


//线程池的默认拒绝策略为AbortPolicy,即丢弃任务并抛出RejectedExecutionException异常
public static class AbortPolicy implements RejectedExecutionHandler {
    
    public AbortPolicy() { }

   
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() +
                                             " rejected from " +
                                             e.toString());
    }
}

//丢弃任务,但是不抛出异常。 
public static class DiscardPolicy implements RejectedExecutionHandler {
  
    public DiscardPolicy() { }

    
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    }
}

//丢弃队列最前面的任务,然后重新提交被拒绝的任务 
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    
    public DiscardOldestPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll();
            e.execute(r);
        }
    }
}

CPU密集型和IO密集型

了解:IO密集型,CPU密集型:(调优)

池的最大的大小如何去设置! 最大线程该如何定义?

  1. CPU 密集型,几核,就是几,可以保持CPU的效率最高!线程数等于cpu数是最好的了!
package demo7;

import java.util.concurrent.*;

/**
 * 手动创建线程池
 * <p>
 * int corePoolSize,
 * int maximumPoolSize,
 * long keepAliveTime,
 * TimeUnit unit,
 * BlockingQueue<Runnable> workQueue,
 * ThreadFactory threadFactory,
 * RejectedExecutionHandler handler
 */
public class ExecutorsTest2 {

    public static void main(String[] args) {
        
        //获取cpu的核数
        System.out.println(Runtime.getRuntime().availableProcessors());
        //自定义线程池
        ExecutorService executorService = new ThreadPoolExecutor(
                2,
                Runtime.getRuntime().availableProcessors(),//获取cpu核数
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
               new ThreadPoolExecutor.AbortPolicy() //默认 银行满了,还有人进来,不处理这个人,抛出异常
                // new ThreadPoolExecutor.DiscardOldestPolicy()//队列满了, 丢掉任务 ,不会抛出异常
                // new ThreadPoolExecutor.CallerRunsPolicy()//哪来的哪去
               // new ThreadPoolExecutor.DiscardOldestPolicy()//队列满了,尝试和最早的竞争,不会抛出异常
        );

        try {
            //最大承载 = 队列 deque + max
            //超出抛出RejectedExecutionException 异常
            for (int i = 1; i <= 10; i++) {
                executorService.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "=>ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭线程池
            executorService.shutdown();
        }
    }
}

  1. IO 密集型 > 判断你程序中十分耗IO的线程, 假如 程序有 15个大型任务, io十分占用资源!可以设置线程为30,大约两倍。

参考链接

posted @ 2020-05-30 15:32  我有满天星辰  阅读(0)  评论(0编辑  收藏  举报