java join yield_Java多线程中join、yield、sleep方法详解
在Java多线程编程中,Thread类是其中一个核心和关键的角色。因此,对该类中一些基础常用方法的理解和熟练使用是开发多线程代码的基础。本篇主要总结一下Thread中常用的一些静态方法的含义及代码中的使用。
sleep方法
源码如下:
/**
* Causes the currently executing thread to sleep (temporarily cease
* execution) for the specified number of milliseconds, subject to
* the precision and accuracy of system timers and schedulers. The thread
* does not lose ownership of any monitors.
*
* @param millis
* the length of time to sleep in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* interrupted status of the current thread is
* cleared when this exception is thrown.
*/
public static native void sleep(long millis) throws InterruptedException;
可以看到sleep是一个静态的本地方法,因为是本地方法,所以并没有java代码的实现,其实是调用了底层的C库函数来实现的睡眠。
有一个long类型的参数,表示睡眠多少毫秒。
阅读注释,sleep方法的含义就是,让当前正在执行任务的线程睡眠(临时地停止执行)指定的毫秒数,这个精度和准确性是用系统时钟和调度器保证的。但是,线程并不会释放它拥有的锁。
注意该方法会抛出InterruptedException中断异常。
sleep不会释放锁代码示例:
public class ThreadsleepDemo{
private Object object = new Object();
public static void main(String[] args) {
ThreadsleepDemo threadsleepDemo = new ThreadsleepDemo();
Thread thread1 = threadsleepDemo.new SleepDemoThread();
thread1.setName("线程1");
Thread thread2 = threadsleepDemo.new SleepDemoThread();
thread2.setName("线程2");
thread1.start();
thread2.start();
}
class SleepDemoThread extends Thread{
@Override
public void run() {
synchronized (object){
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}
}
输出结果如下:
线程1开始运行
线程1运行结束
线程2开始运行
线程2运行结束
可以多运行几次,可能会有线程1在上面或和线程2在上面,但始终都是一个行程运行完了才会运行另一个线程,中间不会插入进来一个线程运行。
yield方法
/**
* A hint to the scheduler that the current thread is willing to yield
* its current use of a processor. The scheduler is free to ignore this
* hint.
*
*
Yield is a heuristic attempt to improve relative progression
* between threads that would otherwise over-utilise a CPU. Its use
* should be combined with detailed profiling and benchmarking to
* ensure that it actually has the desired effect.
*
*
It is rarely appropriate to use this method. It may be useful
* for debugging or testing purposes, where it may help to reproduce
* bugs due to race conditions. It may also be useful when designing
* concurrency control constructs such as the ones in the
* {@link java.util.concurrent.locks} package.
*/
public static native void yield();
当前线程对调度器的一个暗示,表示愿意让出CPU执行器的当前使用权,但是调度器可以自由忽略这个提示。
Yeild是一种在可能会过度使用一个CPU的多个线程之间提升相对进度试探性尝试。它的使用应该结合详细的性能分析和基准测试来进行,确保它确实有预期的效果。
很少使用这种方法。 它可能对调试或测试有用,可能有助于根据竞态条件重现错误。 在设计并发控制结构(例如java.util.concurrent.locks包中的并行控制结构)时也可能有用。
join方法
join有三个重载的方法
join()
join(long millis)
join(long millis,int nanoseconds)
主要看下第二个方法的源码
/**
* Waits at most {@code millis} milliseconds for this thread to
* die. A timeout of {@code 0} means to wait forever.
*
*
This implementation uses a loop of {@code this.wait} calls
* conditioned on {@code this.isAlive}. As a thread terminates the
* {@code this.notifyAll} method is invoked. It is recommended that
* applications not use {@code wait}, {@code notify}, or
* {@code notifyAll} on {@code Thread} instances.
*/
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
就是等待一个线程指定毫秒数后再消亡。无参数的join方法其实就是调用了join(0),即永远等待下去。不过通过源码我们可以看到,在while循环中有一个条件判断,即isAlive()方法,意思是如果当前线程还活着,就会一直等待下去。
有点懵,看个例子应该加深下理解。比如睡前想刷个抖音。
刷抖音的工作我们交给一个线程来完成。
public class ScanDouyin extends Thread{
// 浏览抖音的时长
private int scanTime;
public ScanDouyin(String name, int scanTime){
super(name);
scanTime = this.scanTime;
}
@Override
public void run() {
System.out.println(getName() + ":开始刷抖音了");
try {
// 刷抖音的时间
sleep(scanTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() +":抖音刷完了,睡觉吧");
}
}
下面是准备睡觉的线程
/**
* 准备睡觉了,睡前想要刷个抖音
*/
public class ReadySleep extends Thread{
private ScanDouyin scanDouyin;
public ReadySleep(String name,ScanDouyin scanDouyin){
super(name);
this.scanDouyin = scanDouyin;
}
@Override
public void run() {
System.out.println(getName() + ":准备开始睡觉啦");
try {
// 睡前刷把抖音
scanDouyin.join();
// 准备睡觉的具体内容
System.out.println("开始睡觉");
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + ":zzzzzzzz,已经睡着了");
}
public static void main(String[] args) {
ScanDouyin scanDouyin = new ScanDouyin("刷抖音线程",10000);
ReadySleep readySleep = new ReadySleep("睡觉线程",scanDouyin);
readySleep.start();
scanDouyin.start();
}
}
输出结果如下:
睡觉线程:准备开始睡觉啦
刷抖音线程:开始刷抖音了
刷抖音线程:抖音刷完了,睡觉吧
开始睡觉
睡觉线程:zzzzzzzz,已经睡着了
这里我们我设置的刷抖音的时间是10s,睡觉线程的执行时间是100ms,也就是0.1s。
可以看到因为在睡觉线程中调用了刷抖音线程的join方法,使得睡觉的线程必须等待直到刷完抖音(刷抖音线程执行完毕,线程消亡),才能开始睡觉。
至此,应该可以明白,如果某个线程在另一个线程t上调用t.join(),此线程将被挂起,直到目标线程t结束才恢复(即t.isAlive()方法返回假)。
java join yield_Java多线程中join、yield、sleep方法详解相关推荐
- java.equal例子_Java中的== 和equals()方法详解与实例
Java中的== 和equals()方法: Java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型. byte,short,char,int,long,float,double,boo ...
- java中迭代器要导包吗_java 中迭代器的使用方法详解
java 中迭代器的使用方法详解 前言: 迭代器模式将一个集合给封装起来,主要是为用户提供了一种遍历其内部元素的方式.迭代器模式有两个优点:①提供给用户一个遍历的方式,而没有暴露其内部实现细节:②把元 ...
- php中this的使用技巧,JavaScript中this关键字使用方法详解
JavaScript中this关键字使用方法详解 在面向对象编程语言中,对于this关键字我们是非常熟悉的.比如C++.C#和Java等都提供了这个关键字,虽然在开始学习的时候觉得比较难,但只要理解了 ...
- java调用javascript函数_[Java教程]JavaScript函数的4种调用方法详解
[Java教程]JavaScript函数的4种调用方法详解 0 2016-08-09 00:00:12 在JavaScript中,函数是一等公民,函数在JavaScript中是一个数据类型,而非像C# ...
- android json mysql_Android通过json向MySQL中读写数据的方法详解【读取篇】
本文实例讲述了Android通过json向MySQL中读取数据的方法.分享给大家供大家参考,具体如下: 首先 要定义几个解析json的方法parseJsonMulti,代码如下: private vo ...
- java 三种将list转换为map的方法详解
这篇文章主要介绍了java 三种将list转换为map的方法详解的相关资料,需要的朋友可以参考下 java 三种将list转换为map的方法详解 在本文中,介绍三种将list转换为map的方法: 1) ...
- 在HTML文档中使用JavaScript的方法详解
在HTML文档中使用JavaScript的方法详解 本文详细介绍,在HTML文档(也称为HTML页面或网页)中使用JavaScript脚本代码的多种方法. 假设要用JS生成字符☆直角三角形 实现Jav ...
- 无刷新跳转—关于history中pushState和replaceState方法详解
〝 古人学问遗无力,少壮功夫老始成 〞 **关于history中pushState和replaceState方法详解,**常码字不易,出精品更难,没有特别幸运,那么请先特别努力,别因为懒惰而失败,还矫 ...
- java mod %区别_Java中 % 与Math.floorMod() 区别详解
%为取余(rem),Math.floorMod()为取模(mod) 取余取模有什么区别呢? 对于整型数a,b来说,取模运算或者取余运算的方法都是: 1.求 整数商: c = a/b; 2.计算模或者余 ...
最新文章
- AVR单片机计算器C语言源程序,AVR单片机简单计算器的Proteus仿真实现+源码
- 马斯克称特斯拉Model Y今年产量有限 明年会大规模生产
- SFB 项目经验-82-Active Directory Replication Status
- linux eclipse web项目,Eclipse中web项目部署至Tomcat步骤
- 从0开始python后端开发_配置apache服务器(Mac系统)
- 痕迹清理 - Linux
- 关注手机病毒:重点手机安全事件盘点
- 基于Tableau探索分析世界银行提供的关于科学技术的数据
- pytorch/tensorflow使用anaconda安装scipy库
- 安全删除硬件并弹出媒体的列表中出现内置硬盘的解决办法.
- debian系统简单介绍
- 高仿富途牛牛-组件化(四)-优秀的时钟
- 【李沐:动手学深度学习pytorch版】第2章:预备知识
- matlab稳定性实验分析,实验 控制系统稳定性分析的MATLAB实现
- 养成类游戏——动物餐厅开发制作
- 如何在 ggplot2 中制作饼图(附示例)
- 关于网络下载的记忆碎片
- iOS应用中增加emoji表情输入功能
- 泛函分析笔记2:赋范空间
- 一文搞清楚Web和WWW是什么?