在上两篇中我们学习线程的概念和如何创建线程,在本篇中我们学习一些线程的方法和线程的状态。

方法

Sleep:线程睡眠

线程休眠指的是让线程暂缓执行以一下,等到了预计时间之后再恢复执行参数是毫秒。当线程启动后,再调用sleep方法,可以让线程进入特定时间的阻塞状态,当时间过去后,在进入运行态。

示例代码如下:

public class T03_Sleep {public static void main(String[] args){testSleep();}static  void testSleep(){new Thread(()->{for (int i = 0; i < 100; i++) {System.out.println("A" + i+ " "+new Date().toString());try {Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}}).start();}
}

当启动此线程后,打印循环变量和当前时间,发现每隔一秒打印一次。这就是我们让线程每打印一次就睡眠一秒,所以才会如从。

值得注意的一点是sleep不会释放对象锁,即使当前线程休眠了,其他线程也无法拿到该runable对象,当该线程休眠结束后,继续执行;

Yield:线程让步

yield() 方法和 sleep() 方法类似,也不会释放“锁标志”,区别在于,它没有参数,即 yield() 方法只是使当前线程重新回到可执行状态,将CPU让出来。然后CPU从所有可执行状态的线程中选择线程执行。所以执行 yield() 的线程有可能在进入到可执行状态后马上又被执行,也可能执行别的线程,他所起到的作用就是将CPU让出,重新选择线程。另外 yield() 方法只能使同优先级或者高优先级的线程得到执行机会,这也和 sleep() 方法不同。

public class T03_Yield {public static void main(String[] args) {testYield();}static void testYield() {new Thread(() -> {for (int i = 0; i < 100; i++) {System.out.println("A" + i);if (i % 10 == 0) Thread.yield();}}).start();new Thread(() -> {for (int i = 0; i < 100; i++) {System.out.println("-----------B" + i);if (i % 10 == 0) Thread.yield();}}).start();}
}

每次对10取余,当余数为零时,执行yield方法(),运行的部分结果如下:

Join:线程等待

若一个线程1需要等待另一个线程2执行完毕后再恢复执行,可以在线程1中调用线程2的join()方法。

public class T03_Join {public static void main(String[] args){testJoin();}static void  testJoin(){Thread t1 = new Thread(()->{for (int i = 0; i < 10; i++) {System.out.println("A" + i);try {Thread.sleep(500);}catch (InterruptedException e){e.printStackTrace();}}});Thread t2 = new Thread(()->{try {t1.join();}catch (InterruptedException e){e.printStackTrace();}for (int i = 0; i < 10; i++) {System.out.println("B" +i);try {Thread.sleep(500);}catch (InterruptedException e){e.printStackTrace();}}});t1.start();t2.start();}
}

因为t2在执行时,调用了t1的join方法,所以t2要想执行完毕,必须等待t1执行完毕。执行效果图如下:

currentThread:获取线程实例

获取实例后,可以从当前线程实例中拿出属性值

    public static void main(String[] args) {//获取线程实例Thread s = Thread.currentThread();//获取实例后可以从实例中拿当前线程的的属性//获得当前线程名称System.out.println(s.getName());//获取当前线程状态System.out.println(s.getState());//获得优先级System.out.println(s.getPriority());//是否存活System.out.println(s.isAlive());}

运行结果如下

setPriority :设置线程优先级

Thread 有自己的最小和最大优先级数值,范围在 1-10。如果不在此范围内,则会报错。另外如果设置的 priority 超过了线程所在组的 priority ,那么只能被设置为组的最高 priority 。最后通过调用 native 方法 setPriority0 进行设置。

/*** 改变线程的优先级*/
public class PriorityTest extends Thread{//定义一个有参数的构造器,用于创建线程时指定namepublic PriorityTest(String name){super(name);}public void run(){for (int i = 0; i < 50; i++) {System.out.println(getName()+",其优先级是:"+getPriority()+",循环变量的值为:"+i);}}public static void main(String[] args){//改变主线程的优先级Thread.currentThread().setPriority(6);for (int i = 0; i < 30; i++) {if (i==10) {PriorityTest low = new PriorityTest("低级");low.start();System.out.println("创建之初的优先级:" + low.getPriority());//设置该线程为最低级的优先级low.setPriority(Thread.MIN_PRIORITY);}if (i==20) {PriorityTest high = new PriorityTest("高级");high.start();System.out.println("创建之初的优先级:" + high.getPriority());//设置该线程为最高级的优先级high.setPriority(Thread.MAX_PRIORITY);}}}
}

运行结果如下:

一直循环到50,之后是另一个线程循环:

线程状态

java中的线程的生命周期大体可分为5种状态。从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态及死亡状态。

1. 新建(NEW):新创建了一个线程对象。

2. 可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

3. 运行(RUNNING):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
4. 阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:

  • (一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
  • (二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
  • (三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

5. 死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

这几种状态的转换如图:

可以通过以下的代码看到一些线程的状态:

public class T04_Threadstate {static class MyThread extends Thread {@Overridepublic void run() {System.out.println(this.getState());for (int i = 0; i < 10; i++) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(i);}}}public static void main(String[] args) {Thread t = new MyThread();System.out.println(t.getState());t.start();try {t.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t.getState());}
}

执行效果如下:能看到新建,运行状态,终止

【并发编程】线程中的Sleep、Yield、Join等api方法方法线程状态转换相关推荐

  1. Java并发编程(中下篇)从入门到深入 超详细笔记

    接上一篇博客笔记:Java并发编程(中上篇)从入门到深入 超详细笔记_未来很长,别只看眼前的博客-CSDN博客https://blog.csdn.net/weixin_53142722/article ...

  2. Java并发编程包中atomic的实现原理

    转载自   Java并发编程包中atomic的实现原理 这是一篇来自粉丝的投稿,作者[林湾村龙猫]最近在阅读Java源码,这一篇是他关于并发包中atomic类的源码阅读的总结.Hollis做了一点点修 ...

  3. 安卓在子线程中实现更新UI界面的三种方法 Handler+Message、runOnUiThread、控件.post()

    1.说明 安卓中UI线程为主线程,更新UI界面必须在主线程中进行,在子线程中实现更新UI界面的三种方法:Handler.RunOnUiThread.控件.post() 2.1 Handler (1)定 ...

  4. Java并发编程(多线程)中的相关概念

    众所周知,在Java的知识体系中,并发编程是非常重要的一环,也是面试中必问的题,一个好的Java程序员是必须对并发编程这块有所了解的. 并发必须知道的概念 在深入学习并发编程之前,我们需要了解几个基本 ...

  5. Java中sleep,wait,yield,join的区别

    sleep() wait() yield() join()用法与区别 1.sleep()方法 在指定时间内让当前正在执行的线程暂停执行,但不会释放"锁标志".不推荐使用. slee ...

  6. 【并发编程】map 基本用法和常见错误以及如何实现线程安全的map类型

    博主介绍: – 我是了 凡 微信公众号[了凡银河系]期待你的关注.未来大家一起加油啊~ 前言 哈希表介绍 哈希表(Hash Table)这个数据结构,在Go语言基础的时候就已经涉及过了.实现的就是ke ...

  7. java lock park_java并发编程-LockSupport中park与unpark基本使用与原理简单分析

    文章目录 java并发编程原理之---park与unpark 基本使用 情况一,先park再unpark,代码举例与分析 情况二,先unpark再park,代码举例与分析 特点 原理之park &am ...

  8. 《尚硅谷高级技术之JUC高并发编程》学习笔记11—— Fork / Join 框架

    文章目录 Fork / Join 框架简介 fork() 方法 join() 方法 Fork / Join 框架的异常处理 入门案例 总结 Fork / Join 框架简介 Fork / Join 它 ...

  9. 并发编程-23J.U.C组件拓展之阻塞队列BlockingQueue 和 线程池

    文章目录 概述 阻塞队列的常用场景 阻塞队列的4种处理方式 JDK 7提供的7个阻塞队列 ArrayBlockingQueue LinkedBlockingQueue PriorityBlocking ...

  10. Java并发编程78讲--29 第29讲:HahMap 为什么是线程不安全的?

    本课时我们主要讲解为什么 HashMap 是线程不安全的?而对于 HashMap,相信你一定并不陌生,HashMap 是我们平时工作和学习中用得非常非常多的一个容器,也是 Map 最主要的实现类之一, ...

最新文章

  1. 使用Photoshop制作网页模板
  2. mongodb3.2系统性学习——5、游标 模糊查询 findAndModify函数
  3. python3 购物车小程序
  4. Flv网络播放器制作全攻略(续)
  5. SpringSecurity相关jar包的介绍
  6. php curl实现get请求,PHP中使用curl实现Get和Post请求 | 严佳冬
  7. nvprof 使用记录; 以及使用 nvprof 查看tensorflow-gpu 核函数运行记录
  8. Linux管道函数使用
  9. C语言变量声明内存分配
  10. 微信小程序实现人脸识别认证
  11. shell脚本之循环语句
  12. 【未解决】【Linux环境】IDEA下搜狗输入法无法光标跟随
  13. mysql数据库两表关联,【mysql两表关联查所有数据】
  14. MES系统在注塑行业中的应用
  15. flutter flutter_screenutil Looking up a deactivated widget‘s ancestor is unsafe.
  16. 影响我此生的几首歌(转载)
  17. 浅谈 css的zoom属性
  18. Linux基础——防火墙(一)
  19. bat如何获取当前Windows系统的桌面路径
  20. linux重装出现cannot load file 5555h,技术员教你解决win7系统重装开机提示cannot load file code:5555h的操作方案...

热门文章

  1. 关于windowsx.h的介绍
  2. http抓包工具推荐WSockExpert/httpwatch/HttpAnalyzer/DebugBar
  3. 结合typedef更为直观的应用函数指针
  4. 莫比乌斯函数_莫比乌斯环:python-matplotlib可视化实现
  5. c语言表达式用法,C语言开发之运算符、表达式用法
  6. 订单信息修改java模型图,java毕业设计_springboot框架的物流运输管理系统订单管理...
  7. JavaScript面向对象及原型 及setTimeout
  8. 服务器的文件共享,服务器文件共享设置
  9. halcon区域腐蚀膨胀算子_OpenCV 图像处理之膨胀与腐蚀
  10. oracle flashback table 参数,Oracle10g中FLASHBACK TABLE语句恢复DML误操作