线程面试相关问题-线程有哪些状态 线程池 线程调用start方法是立即执行了吗 ?

线程有哪些状态?
       Java线程中一共有6种状态,分别为:NEW、RUNNABLE、WAITING、TIMED_WAITING、BLOCKED、TERMINATED,其中RUNNABLE包含READY和RUNNING状态,详情可见下图:


  • 【NEW】:初始状态,线程被构建,但是还没有调用 start 方法
  • 【RUNNABLE】:在Java中包括两种状态,RUNNING和READY
           READY:就绪态,该状态下的线程已经获得执行所需的所有资源,只要CPU分配执行权就能运行;所有就绪态的线程存放在就绪队列中
          RUNNING:获得cpu时间片,正在执行的线程;由于每个cpu同一时刻只能执行一条线程,因此每个cpu每个时刻只有一条线程运行。
     
  • 【BLOCKED】:阻塞状态,表示线程进入等待状态,也就是线程因为某种原因放弃了 CPU 使用权,阻塞也分为几种情况 :
    • 等待阻塞:运行的线程执行了 Thread.sleep 、wait()、 join() 等方法JVM 会把当前线程设置为等待状态,当 sleep 结束、join 线程终止或者线程被唤醒后,该线程从等待状态进入到阻塞状态,重新抢占锁后进行线程恢复
    • 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其他线程锁占用了,那么jvm会把当前的线程放入到锁池中
    • 其他阻塞:发出了 I/O请求时,JVM 会把当前线程设置为阻塞状态,当 I/O处理完毕则线程恢复
  • 【WAITING】:进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)
    • 执行wait()、join()、LockSupport.park()
  • 【TIMED_WAITING】:超时等待状态,该状态不同于WAITING,它可以在指定的时间后自行返回
    • 执行 Thread.sleep(long)、wait(long)、join(long)、LockSupport.park(long)、LockSupport.parkNanos(long)、LockSupport.parkUntil(long)
  • 【TERMINATED】:终止状态,表示当前线程执行完毕

 线程调用start方法是立即执行了吗 ?
        线程不是马上执行的;准确来说,调用start( )方法后,线程的状态从 new 的状态 变成 “READY(就绪)”状态,而不是“RUNNING(运行中)”状态。线程要等待CPU调度,不同的JVM有不同的调度算法,线程何时被调度是未知的。因此,start()方法的被调用顺序不能决定线程的执行顺序

Java线程6种状态 VS 5种状态
        操作系统层面有5种状态(新建、就绪、运行、阻塞、终结)
①分到CPU时间的:运行
②可以分到CPU时间的:就绪
③分不到CPU时间的:阻塞
        Java中的RUNNABLE涵盖了就绪、运行、阻塞I/O

  • 【新建状态】:仅是在语言层面创建了线程对象,还未与操作系统线程关联
  • 【可运行状态(就绪状态)】:指该线程已经被创建(与操作系统线程关联),可以由CPU调度执行
  • 【运行状态】:指获取了CPU时间片运行中的状态
    • 当CPU时间片用完,会从【运行状态】切换至【可运行状态】,会导致线程上下文切换
  • 【阻塞状态】
    • 如果调用了阻塞API,如BIO读写文件,这时该线程实际不会用到CPU,会导致线程上下文切换,进入【阻塞状态】
    • 等BIO操作完毕,会由操作系统唤醒阻塞的线程,转换至【可运行状态】
    • 【可运行状态】的区别是,对【阻塞状态】的线程来说只要它们一直不唤醒,调度器就一直不会考虑调度它们
  • 【终止状态】:表示线程已经执行完毕,生命周期已经结束,不会再切换为其它状态

线程池的核心参数

1.corePoolSize 核心线程数目: 最多保留的线程数
2.maximumPoolSize 最大线程数目: 核心线程+救急线程
3.keepAliveTime 生存时间: 针对救急线程
4.unit 时间单位: 针对救急线程
5.workQueue: 阻塞队列
6.threadFactory 线程工厂: 可以为线程创建时起个好名字
7.handler 拒绝策略: 四种
    

代码演示:        

  public static void main(String[] args) {
        AtomicInteger c = new AtomicInteger(1);
        ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,//核心线程数
                3,//最大线程数  这样就决定了救急线程数只有1个(3-2=1)
                0,//和下面的参数一起决定了救急线程的存活时间 如果线程中没有更多的任务了
                TimeUnit.MILLISECONDS,//那么救急线程只存在0秒 即 没任务了 就会从线程池中释放掉 不会保留在线程池中
                queue,//工作队列 容量为2  即将来这个队列中 最多缓冲两个任务
                r -> new Thread(r,"MyThread"+c.getAndIncrement()),//线程工厂 让我们有机会自己控制线程创建的过程  这里主要是控制了线程的名字
                new ThreadPoolExecutor.AbortPolicy()//拒绝策略
        );
    }

 

pool Sizequeue
初始状态0[ ]

提交一个任务(M1) 新建一个线程

(设置任务持续时间为一个小时)

1[ ]

提交一个任务(M2) 新建一个线程

(设置任务持续时间为一个小时)

2[ ]
提交一个任务(M3) 放入队列2[M3]
提交一个任务(M4) 放入队列2[M3,M4]

提交一个任务(M5) 新建一个救急线程

(设置任务持续时间为一个小时)

3[M3,M4]
提交一个任务(M6) 新建一个线程拒绝策略具体见下

 若不设置任务5的持续时间为一个小时

四种拒绝策略:

1.CallerRunsPolicy
        java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy
        当有新任务提交后,如果线程池没被关闭且没有能力执行,则把这个任务交于提交任务的线程执行,也就是谁提交任务,谁就负责执行任务。这样做主要有两点好处。①新提交的任务不会被丢弃,这样也就不会造成业务损失。②由于谁提交任务谁就要负责执行任务,这样提交任务的线程就得负责执行任务,而执行任务又是比较耗时的,在这段期间,提交任务的线程被占用,也就不会再提交新的任务,减缓了任务提交的速度,相当于是一个负反馈。在此期间,线程池中的线程也可以充分利用这段时间来执行掉一部分任务,腾出一定的空间,相当于是给了线程池一定的缓冲期。

2.AbortPolicy
        java.util.concurrent.ThreadPoolExecutor.AbortPolicy
        拒绝策略在拒绝任务时,会直接抛出一个类型为 RejectedExecutionException 的 RuntimeException,让你感知到任务被拒绝了,于是你便可以根据业务逻辑选择重试或者放弃提交等策略。

3.DiscardPolicy
        java.util.concurrent.ThreadPoolExecutor.DiscardPolicy
        当新任务被提交后直接被丢弃掉,也不会给你任何的通知,相对而言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失。

4.DiscardOldestPolicy
        java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy
        如果线程池没被关闭且没有能力执行,则会丢弃任务队列中的头结点,通常是存活时间最长的任务,这种策略与第二种不同之处在于它丢弃的不是最新提交的,而是队列中存活时间最长的,这样就可以腾出空间给新提交的任务,但同理它也存在一定的数据丢失风险。
线程池的4种拒绝策略_不懂的浪漫的博客-CSDN博客_拒绝策略线程池的4种拒绝策略文章目录线程池的4种拒绝策略1.拒绝时机2.拒绝策略2.1 核心接口2.2 内建实现2.2.1 CallerRunsPolicy2.2.2 AbortPolicy2.2.3 DiscardPolicy2.2.4 DiscardOldestPolicy3.参考1.拒绝时机线程池会在以下两种情况下会拒绝新提交的任务当我们调用 shutdown 等方法关闭线程池的时候,如果此时继续向线程池提交任务,就会被拒绝当任务队列(workQueue)已满,而且线程达到最大线程数(maximuhttps://blog.csdn.net/xiewenfeng520/article/details/106954167?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165521541516780366592332%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165521541516780366592332&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-106954167-null-null.142^v14^pc_search_result_control_group,157^v14^new_3&utm_term=%E6%8B%92%E7%BB%9D%E7%AD%96%E7%95%A5&spm=1018.2226.3001.4187


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值