Java线程的六种状态以及状态间的转换

1. 线程状态

    public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

初始状态(NEW)

新创建了一个线程对象,但还没有调用start()方法。

运行(RUNNABLE)

Java线程中将就绪(READY)和运行中(RUNNING)两种状态笼统的称为“运行”。

线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(READY)。就绪状态的线程在获得CPU时间片后变为运行中状态(RUNNING)。

阻塞(BLOCKED)

这个状态,一般是线程等待获取一个锁,来继续执行下一步的操作

等待(WAITING)

一个线程会进入这个状态,一定是执行了如下的一些代码,例如

  • object.wait()
  • thread.join()
  • LockSupport.park() 等
  • 需要等待其他线程做出一些特定动作(通知或中断)

超时等待(TIMED_WAITING)

这个状态和WAITING状态的区别就是,这个状态的等待是有一定时效的,即可以理解为WAITING状态等待的时间是永久的,即必须等到某个条件符合才能继续往下走,否则线程不会被唤醒。但是TIMED_WAITING,等待一段时间之后,会唤醒线程去重新获取锁。

终止(TERMINATED)

表示该线程已经执行完毕。

2. 线程中的状态转换

在这里插入图片描述

1. 情况一:NEW –> RUNNABLE

  • 当调用了t.start()方法时,由 NEW –> RUNNABLE

2. 情况二: RUNNABLE <–> WAITING

当调用了t 线程用 synchronized(obj) 获取了对象锁后

  • 调用 obj.wait() 方法时,t 线程从 RUNNABLE –> WAITING
  • 调用 obj.notify() , obj.notifyAll() , t.interrupt() 时
    • 竞争锁成功,t 线程从 WAITING –> RUNNABLE
    • 竞争锁失败,t 线程从 WAITING –> BLOCKED

3. 情况三:RUNNABLE <–> WAITING

  • 当前线程调用 t.join() 方法时,当前线程从 RUNNABLE –> WAITING
    • 注意是当前线程在t 线程对象的监视器上等待
  • t 线程运行结束,或调用了当前线程的 interrupt() 时,当前线程从 WAITING –> RUNNABLE

4. 情况四: RUNNABLE <–> WAITING

  • 当前线程调用 LockSupport.park() 方法会让当前线程从 RUNNABLE –> WAITING
  • 调用 LockSupport.unpark(目标线程) 或调用了线程 的 interrupt() ,会让目标线程从 WAITING –> RUNNABLE

5. 情况五: RUNNABLE <–> TIMED_WAITING

t 线程用 synchronized(obj) 获取了对象锁后

  • 调用 obj.wait(long n) 方法时,t 线程从 RUNNABLE –> TIMED_WAITING
  • t 线程等待时间超过了 n 毫秒,或调用 obj.notify() , obj.notifyAll() , t.interrupt() 时
    • 竞争锁成功,t 线程从 TIMED_WAITING –> RUNNABLE
    • 竞争锁失败,t 线程从 TIMED_WAITING –> BLOCKED

6. 情况六:RUNNABLE <–> TIMED_WAITING

  • 当前线程调用 t.join(long n) 方法时,当前线程从 RUNNABLE –> TIMED_WAITING
    • 注意是当前线程在t 线程对象的监视器上等待
  • 当前线程等待时间超过了 n 毫秒,或t 线程运行结束,或调用了当前线程的 interrupt() 时,当前线程从 TIMED_WAITING –> RUNNABLE

7. 情况七:RUNNABLE <–> TIMED_WAITING

  • 当前线程调用 Thread.sleep(long n) ,当前线程从 RUNNABLE –> TIMED_WAITING
  • 当前线程等待时间超过了 n 毫秒,当前线程从 TIMED_WAITING –> RUNNABLE

8. 情况八:RUNNABLE <–> TIMED_WAITING

  • 当前线程调用 LockSupport.parkNanos(long nanos) 或 LockSupport.parkUntil(long millis) 时,当前线 程从 RUNNABLE –> TIMED_WAITING
  • 调用 LockSupport.unpark(目标线程) 或调用了线程 的 interrupt() ,或是等待超时,会让目标线程从 TIMED_WAITING–> RUNNABLE

9. 情况九:RUNNABLE <–> BLOCKED

  • t 线程用 synchronized(obj) 获取了对象锁时如果竞争失败,从 RUNNABLE –> BLOCKED
  • 持 obj 锁线程的同步代码块执行完毕,会唤醒该对象上所有 BLOCKED 的线程重新竞争,如果其中 t 线程竞争 成功,从 BLOCKED –> RUNNABLE ,其它失败的线程仍然 BLOCKED

10. 情况十: RUNNABLE <–> TERMINATED

当前线程所有代码运行完毕,进入 TERMINATED

3. 活跃性

1. 定义

因为某种原因,使得代码一直无法执行完毕,这样的现象叫做活跃性

2. 死锁

有这样的情况:一个线程需要同时获取多把锁,这时就容易发生死锁

package top.nnzi;

/**
 * @Description:
 * @Author: Aiguodala
 * @CreateDate: 2021/4/5 15:52
 */

public class DeadLockTest {
    public static void main(String[] args) {
        final Object A = new Object();
        final Object B = new Object();
        new Thread(()->{
            synchronized (A) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (B) {

                }
            }
        }).start();

        new Thread(()->{
            synchronized (B) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (A) {

                }
            }
        }).start();
    }
}

发生死锁的必要条件

  • 互斥条件
    • 在一段时间内,一种资源只能被一个进程所使用
  • 请求和保持条件
    • 进程已经拥有了至少一种资源,同时又去申请其他资源。因为其他资源被别的进程所使用,该进程进入阻塞状态,并且不释放自己已有的资源
  • 不可抢占条件
    • 进程对已获得的资源在未使用完成前不能被强占,只能在进程使用完后自己释放
  • 循环等待条件
    • 发生死锁时,必然存在一个进程——资源的循环链

定位死锁的方法 : jps + jstack 或者 jconsole

避免死锁的方法

在线程使用锁对象时,顺序加锁即可避免死锁

在这里插入图片描述

3. 活锁

活锁出现在两个线程互相改变对方的结束条件,后谁也无法结束

例如:

package top.nnzi;

/**
 * @Description:
 * @Author: Aiguodala
 * @CreateDate: 2021/4/5 16:07
 */

public class AliveLockTest {
    static int count = 10;
    public static void main(String[] args) {
        new Thread(()->{
            while (count <= 20) {
                try {
                    Thread.sleep(500);
                    System.out.println(Thread.currentThread().getName()+  "   "+count);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count++;
            }
        },"t1").start();

        new Thread(()->{
            while (count >= 0) {
                try {
                    Thread.sleep(500);
                    System.out.println(Thread.currentThread().getName() +  "   "+ count);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count--;
            }
        },"t2").start();
    }
}

死锁与活锁的区别

  • 死锁是因为线程互相持有对象想要的锁,并且都不释放,最后到时线程阻塞,停止运行的现象。
  • 活锁是因为线程间修改了对方的结束条件,而导致代码一直在运行,却一直运行不完的现象。

4. 饥饿

某些线程因为优先级太低,导致一直无法获得资源的现象。

在使用顺序加锁时,可能会出现饥饿现象

4. 实现4种线程的方式

  • 实现Runnable接口
  • 继承Thread类
  • 实现Callable接口
  • 线程池

5. 终止线程的方式

  • 标志位,volatile修饰
  • interrupt() 打断
  • stop() 弃用,因为线程会立即停止。可能会一些资源没有及时清理或者释放所有的锁之后同步代码块中的赋值没有处理完。

博客

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程有以下几种状态: 1. New(新建):当一个Thread类或者Runnable接口的实例被创建时,该线程处于新建状态。 2. Runnable(可运行):当调用start()方法启动一个线程时,该线程处于可运行状态线程在此状态下可能正在等待CPU时片,也可能正在执行。 3. Blocked(阻塞):当线程在等待某个对象的锁时,该线程处于阻塞状态。 4. Waiting(等待):当线程在等待某个条件时,该线程处于等待状态。例如,调用了wait()方法或join()方法时,线程会进入等待状态。 5. Timed Waiting(计时等待):当线程执行了sleep()方法、调用了带有超时参数的join()方法或wait()方法时,线程会进入计时等待状态。 6. Terminated(终止):当线程的run()方法执行结束时,该线程处于终止状态线程状态之间转换如下: 1. New -> Runnable:调用start()方法启动线程。 2. Runnable -> Blocked:线程在等待某个对象的锁时,会进入阻塞状态。 3. Runnable -> Waiting:线程调用了wait()方法或join()方法时,会进入等待状态。 4. Runnable -> Timed Waiting:线程调用了sleep()方法或带有超时参数的join()方法时,会进入计时等待状态。 5. Blocked -> Runnable:线程获取到了对象的锁,会进入可运行状态。 6. Waiting -> Runnable:线程等待的条件满足时,会进入可运行状态。 7. Timed Waiting -> Runnable:计时等待时到达时,会进入可运行状态。 8. Runnable -> Terminated:线程的run()方法执行结束时,会进入终止状态

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值