stop()、suspend()、Thread.sleep()都不會釋放線程所持有的鎖。但join()、park()、yield()會不會釋放當前線程持有的鎖?下面通過一些實例來驗證一下
代碼如下
import java.util.Date; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; public class ThreadLockTest { public static void main(String[] args) throws InterruptedException { // yieldTest(10); // parkTest(); // joinTest(); } /** * 測試yield會不會釋放鎖:yield調用的是本地方法,建議seconds設置大一些結果更明顯 * 結論:yield不會釋放線程持有的鎖 * * @param seconds */ private static void yieldTest(int seconds) { String lock = "lock"; //首先執行並獲得鎖 Thread preThread = new Thread() { @Override public void run() { synchronized (lock) { log("=============獲取了鎖=============="); long start = System.currentTimeMillis(); while (true) { //將讓出當前線程的執行權,線程狀態由RUNNING ----> RUNNABLE log(".........yield()被調用"); yield(); long currentTimeMillis = System.currentTimeMillis(); if (currentTimeMillis - start >= 1000 * seconds) { log("---------釋放鎖並結束線程"); break; } } } } }; preThread.setName("preThread"); preThread.start(); //在preThread之后執行的線程 new Thread(() -> { try { Thread.sleep(1000); synchronized (lock) { log("=============獲取了鎖=============="); } } catch (InterruptedException e) { } },"postThread").start(); } /** * 測試park會不會釋放鎖 * 結論:park不會釋放線程持有的鎖 */ private static void parkTest() throws InterruptedException { String lock = "lock"; ////首先執行並獲得鎖 Thread preThread = new Thread(() -> { log("運行...."); synchronized (lock) { log("=============獲取了鎖=============="); log(".........park被調用"); //沒被喚醒就會一直等待 LockSupport.park(); log("被unpark....."); } },"preThread"); preThread.start(); //在preThread之后執行的線程 new Thread(() -> { try { log("運行...."); Thread.sleep(100); log("+++++++++等待獲取鎖"); synchronized (lock) { log("=============獲取了鎖=============="); } } catch (InterruptedException e) { } },"postThread").start(); //主線程等待10秒,然后喚醒preThread線程 TimeUnit.SECONDS.sleep(10); log("主線程喚醒unpark...."); LockSupport.unpark(preThread); } /** * 測試 join 會不會釋放鎖 * 結論:join不會釋放線程持有的鎖 */ private static void joinTest() { String lock = "lock"; //任務線程 Thread taskThread = new Thread(() -> { log("*********任務線程啟動!"); long currentTimeMillis = System.currentTimeMillis(); while (true) { //執行任務需要10秒 if (System.currentTimeMillis() - currentTimeMillis > 10000) { log("任務執行完畢!*********"); return; } } },"taskthread"); //首先執行並獲得鎖 Thread preThread = new Thread(() -> { log("運行...."); try { synchronized (lock) { log("=============獲取了鎖=============="); //啟動線程2並一直等待線程taskThread完成 taskThread.start(); log(".........join被調用"); taskThread.join(); log("---------join執行完畢"); } } catch (InterruptedException e) { } },"preThread"); preThread.start(); //在preThread之后執行的線程 Thread postThread = new Thread(() -> { try { log("運行...."); Thread.sleep(1000); log("+++++++++等待獲取鎖"); synchronized (lock) { log("=============獲取了鎖=============="); } } catch (InterruptedException e) { } },"postThread"); postThread.start(); } /** * 日志打印 * * @param msg */ private static void log(String msg) { System.out.println(new Date() + " " + Thread.currentThread().getName() + " " + msg); } }
運行結果可以自定粘貼運行,結論如下
join()、park()、yield()不會釋放當前線程持有的鎖!