(三)深入并发编程之线程池

深入并发编程之线程池


前言

前两个章节的代码只是做个演示,其实是存在问题的,我们再来看一下:

public class TestThreadSafe {

    int num = 0;
    Lock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        TestThreadSafe t = new TestThreadSafe();
        for (int i = 0; i < 100; i++){
            new Thread(t::test).start();
        }
        TimeUnit.SECONDS.sleep(2);
        System.out.println(t.num);
    }
    void test(){
        lock.lock();
        try {
            num++;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

1:我们是在循环中 new Thread,线程无法复用,这样会导致资源的浪费。
2:工作中多线程一般都是处理任务的,我们并不知道处理时间是多长,所以让主线程sleep是错误的。


线程池

1.1. 线程池的创建

    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                1,  // 核心线程数
                2, // 最大线程数
                60, // 线程存活时间
                TimeUnit.SECONDS, // 存活时间单位
                new LinkedBlockingQueue<>(),// 阻塞队列
                Executors.defaultThreadFactory(),// 线程工厂
                new ThreadPoolExecutor.AbortPolicy());// 拒绝策略
    }

不推荐使用Executors创建,因为业务不同、部署在不同的服务器上,我们自定义可以更为的精细。

1.2. 线程池的使用

在这里插入图片描述
在这里插入图片描述

我们可以看到,线程池在执行任务的时候,execute 需要 Runnable ,submit 需要 Runnable 或 Callable

这里,我们需要回顾一下。

Runnable:无返回值,不能抛出异常。
Callable:有返回值,可以抛出异常。

在这里插入图片描述

1.3. execute底层实现

在这里插入图片描述

1:获取当前工作线程数。
2:如果当前工作线程数 < 核心线程数,则添加一个worker。
3:如果当前没有空闲线程,则判断以下当前线程池状态,如果时running,则进入队列,并且新增一个空任务的worker。
4:否则直接拒绝任务。

在这里插入图片描述

我们可以发现,所谓的addWorker就是创建了一个新的线程,然后调用start方法。那么run的是什么呢?我们继续往下看:

在这里插入图片描述

发现线程复用的原理时一个whille循环,它会不断的去取任务,如果没任务则会一直阻塞。

1.4. 线程池的状态

在这里插入图片描述

在这里插入图片描述

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值