Article Outline
Java多线程之join、yield、sleep
yield方法
这个方法感觉平时是用的最少的
1、调用yield会让当前线程从Running进入Runnable状态,然后调度执行其他同优先级的线程,如果此时没有同优先级的线程,那么不能保证让当前线程暂停的效果。
2、具体的实现依赖于操作系统的任务调度器。
这里提到的 Running就是运行中的状态,而Runnable 对应了操作系统的就绪状态。
sleep方法
1、调用sleep方法会让当前线程从Running进入Timed_waiting状态
2、其他线程可以使用interrupt()方法打断正在睡眠的线程,此时sleep方法会抛出interredException
3、睡眠结束后的线程未必会立刻执行
public class Thread1 {
public Logger LOGGER = LoggerFactory.getLogger(Thread1.class);
@Test
public void test() {
Thread thread = new Thread("t1") {
public void run() {
try {
LOGGER.info("begin sleep");
Thread.sleep(3000);
} catch (InterruptedException e) {
LOGGER.info("wake up"+e.getMessage());
e.printStackTrace();
}
}
};
thread.start();
try {
Thread.sleep(500);
LOGGER.info("唤醒");
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
7:14:31.063 INFO 12708 --- [ t1] com.example.demo.Thread1 : begin sleep
2021-01-08 17:14:31.575 INFO 12708 --- [ main] com.example.demo.Thread1 : 唤醒
2021-01-08 17:14:31.576 INFO 12708 --- [ t1] com.example.demo.Thread1 : wake upsleep interrupted
java.lang.InterruptedException: sleep interrupted
at java.base/java.lang.Thread.sleep(Native Method)
at com.example.demo.Thread1$1.run(Thread1.java:22)
sleep的另类用法!!!!!!
利用sleep防止CPU占用100%
sleep 在没有利用cpu来计算时,不要让while(ture)一直占用cpu,这时可以使用yield或者sleep来让出cpu的使用权给其他程序
注意,sleep的时间不用太大,只要有sleep就ok,因为sleep会使程序让出CPU时间,给其他程序使用,尤其单核cpu的情况下,不加sleep会使cpu的占用率达到90%+
可以使用wait或者条件变量达到类似的效果
不同的是,后两种都需要加锁,并且需要相应的唤醒操作,一般适用于要进行同步的场景
sleep适用于无需锁同步的场景。
join方法
join方法用来等待线程执行结束
例子如下:
public class Test2 {
Logger LOGGER = LoggerFactory.getLogger(Test2.class);
static int r = 0;
@Test
public void test() {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
LOGGER.info("begin");
TimeUnit.SECONDS.sleep(1);
r = 10;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
LOGGER.info("r= " + r);
}
}
2021-01-08 23:53:35.591 INFO 8212 --- [Thread-1] com.example.demo.Test2: begin
2021-01-08 23:53:35.592 INFO 8212 --- [main] com.example.demo.Test2: r= 0
/*可以看到,输出的结果并不是r=10,因为线程休眠了1秒,而主线程在启动了t1线程后,没有等待1秒,直接继续向下执行了输出操作,解决的方案就是,让主线程输出前,等待t1线程执行结束。
*/
t1.start();
t1.join();
LOGGER.info("r= " + r);
}
在添加join之后,输出结果如下:
2021-01-09 00:03:45.855 INFO 9652 --- [Thread-1] com.example.demo.Test2 : begin
2021-01-09 00:03:46.871 INFO 9652 --- [main] com.example.demo.Test2 : r= 10
下一个问题
因为join可以设置等待时间,那么,如果join的时间大于实际线程执行的时间会怎么样呢?
t1.start();
t1.join(3000);
LOGGER.info("r= " + r);
}
这里把时间等待3秒,而实际线程1秒就可以完成。
运行结果如下:
2021-01-09 00:18:20.047 INFO 8968 --- [Thread-1] com.example.demo.Test2 :begin
2021-01-09 00:18:21.053 INFO 8968 --- [main] com.example.demo.Test2 :r= 10
可以看到,代码会以线程和等待较短的时间为准。