Java并发编程初级篇(三):线程状态以及状态转换过程
Java并发编程初级篇(三):线程状态以及状态转换过程
阿拉德大陆的魔法师 发表于1年前
Java并发编程初级篇(三):线程状态以及状态转换过程
  • 发表于 1年前
  • 阅读 44
  • 收藏 1
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 下面我们来看一下线程相关的状态,已经状态转换过程。

线程状态:

  • NEW:当一个线程被创建之初,那么此时线程就是新生状态,此状态下线程已经分配完毕内存空间。
  • RUNNABLE:当调用Thread.start()方法后,线程进入就绪状态,此时线程并不会马上开始执行。需要等待JVM选中并分配CPU时间才能开始执行。
  • RUNNING:线程被分配CPU时间后,进入执行状态,在此状态下会运行run()方法中定义的代码。
  • BLOCKED:当处于运行状态的线程,调用一个被阻塞的方法;试图获取一个正在被其他线程占用的锁,都会进入阻塞状态。
  • WAITING:等待状态。当调用了Object.wait()Thread.join()LockSupport.park();方法后线程会进入等待状态。调用Object.wait()的线程会等待Object.notify()方法的调用而重新进入就绪状态。调用Thread.join()方法的线程会等待调用方法线程执行结束而进入结束状态。
  • TIMED_WAITING:固定时间等待状态。此状态下的线程都有一个固定的等待时间,通过调用Object.wait(Long)Thread.sleep(Long)Thread.join(Long),都会让线程进入此状态。处于此状态的线程会等待指定的时间,然后恢复执行。
  • TERMINATED:线程执行结束。

状态转换图:

线程状态转换函数:

  • new Thread():线程创建之初,线程状态为初始状态NEW。
  • Thread.start():线程状态为RUNNABLE,等待JVM分配CUP时间来执行。
  • Thread.sleep(long):线程进入TIMED_WAITING状态,不释放线程持有的锁,会释放计算资源,并等待指定时间后恢复。
  • Object.wait()/Objectwait(long):前者线程进入WAITING状态,并等待被唤醒;后者线程进入TIMED_WAITING,等待指定时间后恢复。但是wait()方法与sleep()方法不同,它会释放线程持有的锁。
  • Thread.join()/Thread.join(long):前者线程进入WAITING状态,并等待加入的线程执行完毕后恢复;后者线程进入TIMED_WAITING,等待指定时间后恢复。
  • synchronized:等待获取锁会使线程进入BLOCKED状态,并一直竞争这个锁,知道获取锁后进入同步块方法,并恢复RUNNABLE状态。

状态转换示例:

定义一个WaitRunnable线程对象,在run()方法中加锁并调用wait()方法模拟等待资源。

public class WaitRunnable implements Runnable{
    @Override
    public void run() {
        System.out.printf("%s:开始执行,准备锁定object。\n", Thread.currentThread().getName());
        synchronized (Main.object) {
            try {
                System.out.printf("%s:成功锁定object,执行同步模块。\n", Thread.currentThread().getName());
                Thread.sleep(3000);
                System.out.printf("%s:被挂起,等待其他线程唤醒自己。\n", Thread.currentThread().getName());
                Main.object.wait();
                System.out.printf("%s: 被唤起,继续开始执行。\n", Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.printf("%s: 执行结束。", Thread.currentThread().getName());
    }
}

定义一个NotifyRunnable线程对象,在run()方法中加锁,并调用notify()方法来唤醒WaitRunnable线程。

package oschian.section_03;

/**
 * Created by hadoop on 2016/11/22.
 */
public class NotifyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.printf("%s:开始执行,准备锁定object。\n", Thread.currentThread().getName());
        synchronized (Main.object) {
            System.out.printf("%s:成功锁定object,执行同步模块。\n", Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.printf("%s: 唤醒其他线程。\n", Thread.currentThread().getName());
            Main.object.notify();
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.printf("%s: 执行结束。\n", Thread.currentThread().getName());
    }
}

定义主方法类,启动两个线程,并打印线程状态。

public class Main {
    public static final Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new WaitRunnable());
        Thread thread2 = new Thread(new NotifyRunnable());

        System.out.printf("Main: %s:%s , %s:%s\n", thread1.getName(), thread1.getState(), thread2.getName(), thread2.getState());

        thread1.start();
        thread2.start();

        while (thread1.getState() != Thread.State.TERMINATED
                || thread2.getState() != Thread.State.TERMINATED) {
            System.out.printf("Main: %s:%s , %s:%s\n", thread1.getName(), thread1.getState(), thread2.getName(), thread2.getState());
            Thread.sleep(1000);
        }
    }
}

查看控制台日志:

Main: Thread-0:NEW , Thread-1:NEW
Thread-0:开始执行,准备锁定object。
Thread-0:成功锁定object,执行同步模块。
Main: Thread-0:TIMED_WAITING , Thread-1:RUNNABLE
Thread-1:开始执行,准备锁定object。
Main: Thread-0:TIMED_WAITING , Thread-1:BLOCKED
Main: Thread-0:TIMED_WAITING , Thread-1:BLOCKED
Thread-0:被挂起,等待其他线程唤醒自己。
Thread-1:成功锁定object,执行同步模块。
Main: Thread-0:WAITING , Thread-1:TIMED_WAITING
Main: Thread-0:WAITING , Thread-1:TIMED_WAITING
Main: Thread-0:WAITING , Thread-1:TIMED_WAITING
Thread-1: 唤醒其他线程。Main: Thread-0:BLOCKED , Thread-1:TIMED_WAITING
Main: Thread-0:BLOCKED , Thread-1:TIMED_WAITING
Main: Thread-0:BLOCKED , Thread-1:TIMED_WAITING
Thread-1: 执行结束。Thread-0: 被唤起,继续开始执行。Thread-0: 执行结束。

执行过程分析:

1. Thread-0与Thread-1创建之初。

  • Thread-0:NEW
  • Thread-1:NEW

2. Thread-0先启动,获取锁后进入同步方法快并调用sleep方法等待3秒。Thread-1接着启动,也尝试获取锁,但是锁已经被Thread-0获取,Thread-1等待锁释放。

  • Thread-0:NEW->RUNNABLE->TIMED_WAITNG
  • Thread-1:NEW->RUNNABLE->BLOCKED

3. Thread-0等待3秒后继续执行然后调用wait方法挂起,并释放锁。Thread-1获取到锁后开始执行同步快并等待三秒。

  • Thread-0:TIME_WAITING->RUNNABLE->WAITING
  • Thread-1:BLOCKED->RUNNABLE->TIMED_WAITING

4. Thread-1休眠3秒后唤醒Thread-0,但这个时候锁依然被Thread-1所拥有,然后Thread-1继续休眠3秒。Thread-0等待Thread-1释放锁。

  • Thread-0:WAITING->BLOCKED
  • Thread-1:TIMED_WAITING->RUNNABLE->TIMED_WAITING

5. Thread-1休眠结束后恢复,并执行完毕同步方法快后结束。Thread-0获取锁后恢复,执行完同步方法快后结束。

  • Thread-0:BLOCKED->RUNNABLE->TERMINATED
  • Thread-1:TIMED_WAITING->RUNNABLE->TERNINATED

 

共有 人打赏支持
粉丝 21
博文 91
码字总数 83019
×
阿拉德大陆的魔法师
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: