文档章节

Java并发编程初级篇(三):线程状态以及状态转换过程

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/22 12:11
字数 1338
阅读 66
收藏 2

线程状态:

  • 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

 

© 著作权归作者所有

共有 人打赏支持
阿拉德大陆的魔法师
粉丝 24
博文 91
码字总数 83019
作品 0
西城
程序员
读书笔记之《Java并发编程的艺术》-并发编程基础

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
8
【死磕Java并发】-----J.U.C之AQS:CLH同步队列

此篇博客所有源码均来自JDK 1.8 在上篇博客【死磕Java并发】-----J.U.C之AQS:AQS简介中提到了AQS内部维护着一个FIFO队列,该队列就是CLH同步队列。 CLH同步队列是一个FIFO双向队列,AQS依赖...

chenssy
2017/06/09
0
0
读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
读书笔记之《Java并发编程的艺术》-java中的锁

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

学习大数据为什么要先学Java?

计算机编程语言有很多,目前用的多一点的就是Java,C++,Python等等。目前大多数学习大数据的人都是选择学习Java,那Java到底好在哪呢?为什么学大数据之前要先学Java呢?我们今天就来分析一...

董黎明
11分钟前
0
0
php删除服务器所有session

php删除服务器所有session踢掉所有在线用户linux 注意:如果要删除服务器上所有session,重启php服务是解决不了问题的,php的session是持久化的。 有效解决办法: 删除 /tmp 下的所有文件(默...

妖尾巴
17分钟前
0
0
Ubuntu18.04 安装最新版WPS

1.手动卸载libreoffice:sudo apt-get remove --purge libreoffice* 2.官网下载WPS和字体: WPS:http://wps-community.org/download.html 字体:http://wps-community.org/download.html?vl......

AI_SKI
45分钟前
4
0
数据结构(算法)-图(深度优先搜索 DFS)

#include <iostream>using namespace std;#define MaxVex 30typedef char VertexType;typedef struct vexNode adjList[MaxVex];struct edgeNode{int adjvex;//邻接点......

ashuo
50分钟前
1
0
1024 搞事倒计时!距程序员节还有 2 天!

详情请关注微信公众号:七牛云

七牛云
50分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部