join()、park()、yield()会不会释放当前线程持有的锁?
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()不会释放当前线程持有的锁!