1. 程式人生 > >java執行緒阻塞喚醒、interrupt測試

java執行緒阻塞喚醒、interrupt測試

執行緒阻塞可以採用Object.wait()、Object.notify()來控制執行緒的阻塞喚醒。

另一種方式是呼叫Unsafe.park()、Unsafe.unpark()。

在主動呼叫執行緒interrupt方法之後,目標執行緒如果正在block狀態就會被喚醒,通過Object.wait()、Unsafe.park()控制的阻塞都會被喚醒並直接往下執行,但是如果執行後面的邏輯中再次碰到Object.wait()就會再次被阻塞,而如果是碰到Unsafe.park()執行緒則會直接往下執行。測試程式碼如下


public class InterruptTest {
	public static void main(String[] args) {
		String t1b = "t1 block";
		final Thread t1 = new Thread(()->{
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < 10000000; i++) {
				sb.append(i ^ 100);
			}
			try {
				synchronized (t1b) {
					t1b.wait();
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(1);
			LockSupport.park(t1b);//park 線上程被標識為interrupt之後會直接往下執行
			//Object.wait() 線上程標識為interrupt之後還是會阻塞
			try {
				synchronized (t1b) {
					t1b.wait();
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(2);
		});
		t1.start();
//		try {
//			Thread.sleep(500);
//		} catch (InterruptedException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		//執行緒如果正在wait、sleep中會直接丟擲一個InterruptedException異常並且往下執行,如果再次碰到wait、sleep那還是會被阻塞
		//執行緒如果是RUNNING狀態,之後第一次遇到wait或者sleep也會丟擲InterruptedException異常並且往下執行,但是再次遇到wait、sleep時還是會被阻塞
		//如果是park則都會直接跳過並且不丟擲異常
		t1.interrupt();
	}