线程池的学习

Executors(线程池工具类)

不建议使用 ,主要是为了展现 ThreadPoolExecutor 不同参数,所展现的不同效果

以 外包 公司 接项目 为例子 , 一个员工只可以 干 一个 项目 ,

例子 就是 公司 接了100个项目

public class Test01 {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
            executorService = Executors.newFixedThreadPool(10);
//            executorService = Executors.newSingleThreadExecutor();


        for (int i = 1; i <= 100; i++) {
            executorService.execute(new MyTask(i));
        }
        System.out.println("项目发放完毕");
    }
}

class MyTask implements Runnable {
    int name;

    public MyTask(int i) {
        name = i;
    }

    @Override
    public void run() {

        System.out.println(Thread.currentThread().getName()+" 接了 第"+name+" 项目");
        int random = (int) (Math.random()*10000+1000);
//        System.out.println(random);
        SleepTools.ms(random);
    }
}
  • newCachedThreadPool

    • 这个 线程池  核心线程为 0 , 最大线程 为int的最大值(非常大),活跃时间为1个小时,阻塞队列为SynchronousQueue(同步)
    • 当 这个 池接到了 100个项目 , 就会把第一个项目放到阻塞队列,发现没有核心员工,招聘一个,依次这样,就会招聘 100个 临时员工 , 工作的速度非常快
    • SynchronousQueue(典型的 生产者 和 消费者),里面只能存一个元素
    • 导致 第几个任务 会对应 招聘的第几个 员工
    •  如果 假设 每一个 员工都是 大佬 ,解决项目的速度非常快,就会出现这样的现象
      • 解释 : 假设当70 个项目 接到时 公司里已经有 员工 结束了手里的项目 那么就没必要 再招聘了
  • newFixedThreadPool

    • 这个 线程池  核心线程为 所传的值, 最大线程 为所传的值,活跃时间 只对临时的有用,所以这个直接为0 阻塞队列 为 LinkedBlockingQueue
    • 当 这个 池接到了 100个项目 ,就会全部交给 核心员工,因为最大的线程 和 核心线程相等,就会导致,无法招聘临时工,其他的项目只能,等,
    • LinkedBlockingQueue无 界 队列 这队列 可以 存放 int MAX个元素 和无线大差不多
  • newSingleThreadExecutor

    • 这个 线程池  核心线程为 1, 最大线程 1,活跃时间 只对临时的有用,所以这个直接为0,阻塞队列为LinkedBlockingQueue
    • 当 这个 池接到了 100个项目 ,一个一个交给 这个核心员工,直接累死。速度也是非常慢
  • 不推荐的原因
    • 容易 OOM
    • 而且 newFixedThreadPool 和  newSingleThreadExecutor还容易 内存 100%
      • 原因 就是无界队列 ,队列存的数据 ,肯定占用内存 ,如果 无限次数的存 , 内存肯定 会炸
    • newCachedThreadPool 这个 导致 cpu 100 % , 因为来一个 就可以 处理一个 虽然 节省了内存 ,但是 cpu 压力巨大

    • 不推荐 就是 阻塞队列 和 线程 的参数 不合适

    • 如果 并发 根本就不高 ,而且 业务 也不是 很复杂 ,随便用,yyds

    • 如果 高并发 业务杂 ,就需要 自定义 线程池

    • 自定义也不难 就是 ThreadPoolExecutor 自己设置参数,权衡一下

      • new ThreadPoolExecutor(10, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20));

      • 参数 解释 如果 当前来了60个任务 ,

        • 20个任务会交给 10个核心 和 10个 非核心来处理

        • 20个会交给 阻塞队列

        • 还有 20 个 会 被拒绝(交给拒绝策略)

        • 60分钟 10个非核心的就会被释放

ThreadPoolExecutor非常重要的一个类

  • 构造参数 (以 外包 公司来解释,一个员工只可以做一个项目)

    • corePoolSize(int) 核心线程数
      • 相当于 外包公司的 核心员工 , 如果接到项目就可以直接做
    • maximumPoolSize(int) 最大线程
      • 相当于 外包公司 可以容纳的 最多员工, 如果项目一下子接了 100个 ,但是核心员工只有20个,但是最大线程 是 50 ,那么就会再去 招聘 30个临时的员工(非核心)
    • keepAliveTime(long) 活跃时间
      • 这个相当于 临时工的 合同 ,一旦到期 就 bye 了
    • workQueue(BlockingQueue) 阻塞队列
    • threadFactory(ThreadFactory) 拒接策略

    • handler(RejectedExecutionHandler)

Executor

  • Executor 的 execute
  • ExecutorService 的  submit

  • AbstractExecutorService 对 submit 进行了 实现,里面调用 了 execute

  • 区别
    • execute 没有返回值
    • submit 有返回值

ThreadPoolExecutor 源码 分析

原码,反码 ,补码

这三个只对 负数 有意义

正数 的 三码 一模一样

负数的 计算

以 8 位为例子

最高位 表示 符号 0为正数 1为负数

  • 负数
  • 原码
    • 就是 转为 二进制 后 最高位变为 0
  • 反码
    • 就是 原码 是数字位 全部 0变1 1变0
  • 补码
    • 就是 反码 加1
原码反码补码
70000 01110000 01110000 0111
-71000 01111111 10001111 1001

计算

  • 6 - 18 
    = 6 + (-18)
    = [0000 0000 0000 0110]补 + [1111 1111 1110 1110]补
    = [1111 1111 1111 0100]补
    =  [1111 1111 1111 0011]反
    = [1000 0000 0000 1100]原
    = -12

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值