join():阻塞当前线程,直到调用join方法的线程执行完毕。
案例:
https://github.com/learning-coding-daily/ConcurrencyStudy
package joinPackage;
/**
* 线程a调用线程b的join方法后被阻塞,
* 会因其他线程调用线程a的interrupt方法,
* 中断线程a抛出异常而返回
*/
public class JoinL {
public static void main(String[] args) {
Thread threadOne = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread one begin");
for (;;){
}
}
});
Thread mainThread = Thread.currentThread();
Thread threadTwo = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
mainThread.interrupt();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
threadOne.start();
threadTwo.start();
try {
threadOne.join();//蹲adc走过来,反被对方打野秒杀(1,2线程是一伙)
} catch (InterruptedException e) {
System.out.println("mainThread e :"+e);
throw new RuntimeException(e);
}
}
}
sleep():让出cpu调度,不让监视器锁资源,到点后,重新参与cpu调度。
期间被其他线程调用interrupt方法,抛interruptedException
案例:
package sleepP;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 线程在睡眠时,监视器锁资源不会释放
*/
public class SleepL {
// 此为独占锁 任意时刻只可被一个线程获取
private static final Lock lock = new ReentrantLock();
public static void main(String[] args) {
Thread threadOne = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
System.out.println("thread one start sleep");
Thread.sleep(1000);
System.out.println("thread one is in awaked");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
lock.unlock();
}
}
});
Thread threadTwo = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
System.out.println("thread two start sleep");
Thread.sleep(1000);
System.out.println("thread two is in awaked");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
threadOne.start();
threadTwo.start();
}
}
yield():当前线程让出cpu资源执行权,并处于就绪状态。(cpu下一次调用也可能是该线程)
中断线程:
interrupt:设置调用该方法的线程中断标记,如果该线程早已被阻塞,报InterruptException异常
isInterrupted:检测调用该方法的线程是否中断。不消除中断标记
interrupted:检测当前线程是否中断。消除中断标记
案例1:
package interruptP;
/**
* 使用中断标记优雅退出线程
*/
public class interruptL {
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted())
System.out.println(Thread.currentThread().getName()+":hello");
}
});
threadA.start();
Thread.sleep(1000);
System.out.println("main thread interrupt threadA");
threadA.interrupt();
threadA.join();
System.out.println("main is over");
}
}
案例2
package interruptP;
/**
* 使用interrupt方法强制阻塞线程抛出异常返回,
* 目的:提前唤醒线程
*/
public class interruptL2 {
public static void main(String[] args) throws InterruptedException {
Thread threada = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("threada will sleep 200000");
try {
Thread.sleep(20000);
System.out.println("threada awaking");
} catch (InterruptedException e) {
System.out.println("threada is interrupted while sleeping");
// throw new RuntimeException(e);
return;
}
System.out.println("threada is normal");
}
});
threada.start();
threada.interrupt();
threada.join();
System.out.println("main thread is over");
}
}
result:
案例3:当前线程是否中断并清楚中断标记
package interruptP;
/**
* 当前线程是否中断并清楚中断标记
*/
public class InterruptL3 {
public static void main(String[] args) throws InterruptedException {
Thread threada = new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().interrupted()){
}
System.out.println("threada is "+Thread.currentThread().isInterrupted());
}
});
threada.start();
threada.interrupt();
threada.join();
System.out.println("main is over");
}
}