文档章节

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

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/22 12:11
字数 1338
阅读 57
收藏 1
点赞 0
评论 0

线程状态:

  • 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

 

© 著作权归作者所有

共有 人打赏支持
阿拉德大陆的魔法师
粉丝 20
博文 91
码字总数 83019
作品 0
西城
程序员
Java多线程学习(四)等待/通知(wait/notify)机制

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀 ⋅ 04/16 ⋅ 0

【Java并发专题】27篇文章详细总结Java并发基础知识

努力的意义,就是,在以后的日子里,放眼望去全是自己喜欢的人和事! github:https://github.com/CL0610/Java-concurrency,欢迎题issue和Pull request。所有的文档都是自己亲自码的,如果觉...

你听___ ⋅ 05/06 ⋅ 0

深入理解多线程(五)—— Java虚拟机的锁优化技术

本文是《深入理解多线程》的第五篇文章,前面几篇文章中我们从synchronized的实现原理开始,一直介绍到了Monitor的实现原理。 前情提要 通过前面几篇文章,我们已经知道: 1、同步方法通过关...

⋅ 04/21 ⋅ 0

Java 面试知识点解析(三)——JVM篇

前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大部...

我没有三颗心脏 ⋅ 05/16 ⋅ 0

Java并发--synchronized实现原理及锁优化

注:本文中的部分内容摘抄自他人博客,如有侵权,请联系我,侵删~ 本篇博客主要讲述 synchronized 关键字的实现原理以及 JDK 1.6 后对 synchronized 的种种优化。synchronized 的使用不再赘述...

championhengyi ⋅ 04/27 ⋅ 0

Java并发机制及锁的实现原理

Java并发编程概述 并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最大限度地并发执行。在进行并发编程时,如果希望通过多线程执行任务让程序运行得更快,会面...

烂猪皮 ⋅ 05/11 ⋅ 0

Java 编程之美:并发编程高级篇之一

本文来自作者 追梦 在 GitChat 上分享 「Java 编程之美:并发编程高级篇之一」 编辑 | 工藤 前言 借用 Java 并发编程实践中的话:编写正确的程序并不容易,而编写正常的并发程序就更难了。 ...

gitchat ⋅ 05/24 ⋅ 0

深入浅出Java多线程,看着篇就够了

Java给多线程编程提供了内置的支持。一个多线程程序包含两个或多个能并发运行的部分。程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径。 多线程是多任务的一种特别的形...

java高级架构牛人 ⋅ 05/22 ⋅ 0

多线程基础必要知识点!看了学习多线程事半功倍

前言 不小心就鸽了几天没有更新了,这个星期回家咯。在学校的日子要努力一点才行! 只有光头才能变强 回顾前面: 多线程三分钟就可以入个门了! Thread源码剖析 本文章的知识主要参考《Java并...

Java3y ⋅ 04/23 ⋅ 0

并发编程包--java.util.Concurrent

java.util.concurrent并发编程包是专门为Java并发编程设计的,其中设计的类主要分为以下几部分: 显式锁 原子变量 线程池 并发容器 同步工具类 1、显式锁 显式锁相关内容可以看这篇博客:htt...

霍淇滨 ⋅ 05/27 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Android JNI 读写Bitmap的方法

Java层创建Bitmap,通过JNI将Bitmap传到C/C++进行处理 Java部分 public static native boolean greenBitmap(Bitmap bitmap); C/C++部分 JNIEXPORT jboolean JNICALL Java_com_test_Test_gree......

国仔饼 ⋅ 22分钟前 ⋅ 0

一次性让你懂async/await,解决回调地狱

什么是async? 欢迎留言讨论 async 函数是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。相较于 Generator,async 函数的改进在于下面四点: 内置执...

阿K1225 ⋅ 22分钟前 ⋅ 0

angular常用命令

.下载更新操作 1.利用npm下载angular的命令行工具AngularCLI: npm install -g @angular/cli 2.下载jquery: npm install --save jquery 3.更新npm: npm i -g npm 4.更新angular: ng update ......

消散了的诗意 ⋅ 25分钟前 ⋅ 0

window.print 页面打印

定义和用法 print() 方法用于打印当前窗口的内容。 语法 window.print(); window.print() 实际上,是浏览器打印功能菜单的一种程序调用。与点击打印功能菜单一样,不能精确分页,不能设置纸型...

初学者的优化 ⋅ 25分钟前 ⋅ 0

魔兽世界 7.0版本上 PVE装备全攻略

  T套 因为大家应该都会打穿副本的所以具体是哪个boss我就不说了。   T1: 所有套装都在【熔火之心】出   T2: 头原来是在【奥妮克希亚的巢穴】改到黑翼之巢的奈法利安了,腿是在【熔火之...

wangchen1999 ⋅ 26分钟前 ⋅ 0

java.math.BigDecimal使用小结

原文地址 java.math.BigDecimal使用小结 divide方法 使用BigDecimal.divide方法时一定要考虑: 除数是否为0 商是否是无限小数 正确的使用方式 判断除数是否为0,是0做另外的处理逻辑 调用除法...

666B ⋅ 29分钟前 ⋅ 0

关于qstring转char乱码问题。

if (OpenClipboard(NULL)) { HGLOBAL hgClip; EmptyClipboard(); QByteArray byay = FValue.toLocal8Bit(); //转latin编码 char *bochsrc_line = byay.data(); hgClip = GlobalAlloc(GMEM_DD......

backtrackx ⋅ 29分钟前 ⋅ 0

了解SSH加密和连接过程

介绍 SSH或安全shell是安全协议,也是安全管理远程服务器的最常用方式。通过使用多种加密技术,SSH提供了一种机制,用于在双方之间建立加密安全连接,对彼此进行身份验证,以及来回传递命令和...

吴伟祥 ⋅ 35分钟前 ⋅ 0

微信小程序

小程序的全局配置app.json 微信小程序的全局配置保存在app.json文件中。开发者通过使用app.json来配置页面文件(pages)的路径、窗口(window)表现、设定网络超时时间值(networkTimeout)以...

上官清偌 ⋅ 38分钟前 ⋅ 0

【转】百度坐标坐标系之间的转换(JS版代码)

/** * Created by Wandergis on 2015/7/8. * 提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换 *///定义一些常量var x_PI = 3.1415926535897932...

HAVENT ⋅ 40分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部