众所周知,操作线程就必须熟读线程的API方法,万一你开个多线程刹不住车就歇菜了,下面就介绍一些API基本用法。包括sleep,join,yield,interrupt。
sleep,让当前线程睡一会。原生用法Thread.sleep(毫秒),会抛出一个打断的异常;此方法可防止CPU100%的问题,如果你代码中有轮训机制,就会体验到。while(true) 中加上一个sleep,CPU至少会减低80%消耗。一般我们采用自制工具类。因为JUC中支持改玩意,不需要每次去catch异常
public class SleepUtils {
public static void sleep(int second){
try {
TimeUnit.SECONDS.sleep(second);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
join是等待调用join线程结束继续运行,一般用于线程间通信。比如t1烧水,t2泡茶两个线程。显然t2需要等t1结束后才能开始,那么就可以使用t1.join()来实现。
join代码展示
@Slf4j
public class Thread03 {
public static int i =0;
public static void main(String[] args) throws Exception{
Thread t1 = new Thread(()->{
log.info("t1 start");
SleepUtils.sleep(1);
i++;
});
t1.start();
t1.join();//必须等t1执行完,否则可能i=0
log.info("t1 start i={}",i);
}
}
yield是指短暂放弃CPU使用权,让其他线程优先执行。这个在处理冷热数据的时候可用上。如t1,t2两个线程都是处理售票,t2可能封面搞了个美女访问量更多,但其实t1,t2两个是同时抢占CPU时间片在运行的,在java层面就可以t1线程使用Thread.yield() 让t2单位时间处理能力更强。
interrupt是打断线程。这里分两种情况,当打断打断运行线程时不会中断服务,会继续执行打断后逻辑,打断后标记为true。当打断阻塞线程 sleep wait join 会中断服务,打断后打断标记仍为false。
interrupt代码展示,这个例子就是线程二阶段打断,判断了运行时打断和阻塞时打断。以及打断标识的处理。
@Slf4j
public class ThreadInterrupt02 {
public static void main(String[] args) {
/**
* 有一个监控线程,如果出现异常则停止,如果未出现继续监控
*/
Monitor monitor = new Monitor();
monitor.start();
SleepUtils.sleep(5);//休眠5s后执行打断操作
monitor.stop();
}
}
@Slf4j
class Monitor {
private Thread monitor;
public void start(){
monitor = new Thread(()->{
while (true){
log.info("monitor 正在监控中");
//判断当前线程上次是否被打断,如果打断直接退出
if (Thread.currentThread().isInterrupted()) {
log.info("monitor 被打断");
break;
}
//如果没退出,休眠2秒继续执行,此过程可能会打断
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
log.info("睡眠被打断");
e.printStackTrace();
Thread.currentThread().interrupt();//如果在睡眠过程被打断,标识仍为false,不会break,所以这里二次打断
}
}
});
monitor.start();
}
public void stop(){
monitor.interrupt();
log.info("线程执行打断");
}
}