文档章节

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

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/22 12:11
字数 1338
阅读 58
收藏 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

 

© 著作权归作者所有

共有 人打赏支持
阿拉德大陆的魔法师
粉丝 22
博文 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并发编程的艺术》-线程池和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中的多线程机制

一、进程与应用程序的区别 进程(Process)是最初定义在Unix等多用户、多任务操作系统环境下用于表示应用程序在内存环境中基本执行单元的概念。以Unix操作系统为例,进程是Unix操作系统环境中...

陶邦仁
2012/11/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

基于名字自动发布之数据库(4)

基于名字自动发布之数据库(4) 项目地址: https://gitee.com/lookingdreamer/RexDeploy_v1 流程图 几个重要的表 数据库表主要包含以下7个表 表名 说明 pre_auto_configure 配置模板关联表 pr...

运维技术
48分钟前
0
0
记一次Redis内存诡异增长

一、现象 实例名:r-bp1cxxxxxxxxxd04(主从) 时间:2017-11-16 12:26~12:27 问题:一分钟内存上涨了2G,如下图所示: 键值规模:6000万左右 二、Redis内存分析 1.内存组成 上图中的内存统计的...

Mr_zebra
51分钟前
3
0
对java中泛型的理解

1. 所有反射的操作都是在运行时的,一般程序会采取去泛型化的操作。 也就是说Java中的泛型只是在编译阶段有效,在编译过程中,正确检验泛型结果后,会将泛型的相关信息抹掉,并且在对象进入和...

-一抹微笑
53分钟前
0
0
monit监控自定义服务

版本:This is Monit version 5.25.1 服务器上跑的公司自己的服务,查看网上写的monit配置监控,都是一些监控常规应用(Nginx、Apache、mysql等)这些监控起来比较简单,都有pid文件,tomca...

骑猪赛大象
56分钟前
0
0
MicroPython新货上架【TPYBoard新品合集】你想要的好玩意儿全在这!

八月火力全开! TPYBoard一大波新品隆重上市! 一次次的研发、尝试 无数次的改进、优化 新品强势来袭 发烧友们期待已久的 STM32F407系列也已全新上线啦~ _________________________________...

bodasisiter
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部