聊聊线程与线程池

原文介绍

原文链接
这篇文章介绍了线程与线程池。

线程状态

在这里插入图片描述
引用原文

第一步,是用new Thread()的方法新建一个线程,在线程创建完成之后,线程就进入了就绪(Runnable)状态,此时创建出来的线程进入抢占CPU资源的状态,当线程抢到了CPU的执行权之后,线程就进入了运行状态(Running),当该线程的任务执行完成之后或者是非常态的调用的stop()方法之后,线程就进入了死亡状态
而我们在图解中可以看出,线程还具有一个阻塞的过程,这是怎么回事呢?当面对以下几种情况的时候,容易造成线程阻塞
第一种,当线程主动调用了sleep()方法时,线程会进入则阻塞状态
除此之外,当线程中主动调用了阻塞时的IO方法时,这个方法有一个返回参数,当参数返回之前,线程也会进入阻塞状态
还有一种情况,当线程进入正在等待某个通知时,会进入阻塞状态
那么,为什么会有阻塞状态出现呢?我们都知道,CPU的资源是十分宝贵的,所以,当线程正在进行某种不确定时长的任务时,Java就会收回CPU的执行权,从而合理应用CPU的资源。我们根据图可以看出,线程在阻塞过程结束之后,会重新进入就绪状态,重新抢夺CPU资源。这时候,我们可能会产生一个疑问,如何跳出阻塞过程呢?又以上几种可能造成线程阻塞的情况来看,都是存在一个时间限制的,当sleep()方法的睡眠时长过去后,线程就自动跳出了阻塞状态,第二种则是在返回了一个参数之后,在获取到了等待的通知时,就自动跳出了线程的阻塞过程

构造方法

public ThreadPoolExecutor(int corePoolSize,//核心线程数大小
                          int maximumPoolSize,//最大线程数
                          long keepAliveTime,//线程活跃时间
                          TimeUnit unit,//当线程数大于核心,这是多余的空闲线程的最长时间,将终止之前等待新任务
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

参数介绍:

  1. corePoolSize 就是线程池中的核心线程数量,这几个核心线程,只是在没有用的时候,也不会被回收
  2. maximumPoolSize 就是线程池中可以容纳的最大线程的数量
  3. keepAliveTime 就是线程池中除了核心线程之外的其他的最长可以保留的时间,因为在线程池中,除了核心线程即使在无任务的情况下也不能被清除,其余的都是有存活时间的,意思就是非核心线程可以保留的最长的空闲时间 。原文翻译:当线程数大于核心,这是多余的空闲线程的最长时间,将终止之前等待新任务
  4. unit 就是计算这个时间的一个单位
  5. workQueue 就是等待队列,任务可以储存在任务队列中等待被执行,执行的是FIFO原则(先进先出)原文翻译:用于在任务暂挂之前用于保留任务的队列 已执行。此队列将仅容纳{@code Runnable} 由{@code execute}方法提交的任务
  6. threadFactory 就是创建线程的线程工厂,可以设置线程名称
  7. handler 是一种拒绝策略,我们可以在任务满了知乎,拒绝执行某些任务,如不指定,java设置了defaultHandler ,其默认值为:AbortPolicy。会抛出异常

拒绝策略

handler的拒绝策略 java提供四种:

  1. AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满
  2. DisCardPolicy:不执行新任务,也不抛出异常
  3. DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行
  4. CallerRunsPolicy:直接调用execute来执行当前任务

线程池的执行流程

在这里插入图片描述
任务提交到线程池时:
核心线程会直接执行任务。继续提交任务,核心线程均处于运行状态时,任务会被添加到workQueue。继续添加任务,当workQueue满了时候会创建线程去执行新提交的任务。继续添加任务,当最大线程数线程均满时,按照拒绝策略处理。

常见线程池

四种常见的线程池:

  1. CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
  2. SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。
  3. SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。
  4. FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程

测试

代码

public static void main(String[] args) {
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setNameFormat("iChen-%s")
                .build();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 7, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), threadFactory);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 1; i <= 11; i++) {
            String taskName = "task" + i;
            System.out.println(taskName + "提交到线程池");
            executor.submit(() -> {
                try {
                    // 打印正在执行的线程信息
                    String threadName = Thread.currentThread().getName();
                    System.out.println("线程:" + threadName + "正在执行" + taskName);
                    Thread.sleep(6000);
                    System.out.println("线程:" + threadName + "执行完毕");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }

测试输出

task1提交到线程池
task2提交到线程池
task3提交到线程池
task4提交到线程池
task5提交到线程池
task6提交到线程池
task7提交到线程池
task8提交到线程池
线程:iChen-0正在执行task1
task9提交到线程池
线程:iChen-1正在执行task2
task10提交到线程池
task11提交到线程池
线程:main正在执行task11
线程:iChen-2正在执行task3
线程:iChen-4正在执行task8
线程:iChen-5正在执行task9
线程:iChen-6正在执行task10
线程:iChen-3正在执行task4
线程:iChen-2执行完毕
线程:iChen-0执行完毕
线程:iChen-2正在执行task5
线程:iChen-0正在执行task6
`线程:main执行完毕`
线程:iChen-1执行完毕
线程:iChen-1正在执行task7
线程:iChen-3执行完毕
线程:iChen-4执行完毕
线程:iChen-5执行完毕
线程:iChen-6执行完毕
线程:iChen-2执行完毕
线程:iChen-1执行完毕
线程:iChen-0执行完毕

相关图片源自网络,侵删

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值