成都络迈品牌网站建设,网站架构师的工作内容,小程序买量平台,网站建设维护 知乎一、wait()
1. 源码#xff1a;
实际调用本地方法
2. 作用
释放当前锁#xff0c;并让当前线程进入等待状态#xff1b;timeoutMillis为等待时间#xff0c;单位毫秒#xff0c;如果为0则表示无限等待下去#xff1b;该方法使用前提是#xff1a;当前执行线程必须持…一、wait()
1. 源码
实际调用本地方法
2. 作用
释放当前锁并让当前线程进入等待状态timeoutMillis为等待时间单位毫秒如果为0则表示无限等待下去该方法使用前提是当前执行线程必须持有该对象的锁该方法为Object对象方法所有Java对象都能调用wait方法因为所有对象都可以成为锁
3. 示例
失败案例
package com.suo.javacode.concurrent;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class WaitJoinTest {static ExecutorService cached Executors.newCachedThreadPool();static final String LOCK_A lock-a;static final String LOCK_B lock-b;public static void main(String[] args) throws InterruptedException {cached.execute(()-{synchronized (LOCK_A) {System.out.println(线程-Thread.currentThread().getName()开始执行);try {LOCK_B.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(线程-Thread.currentThread().getName()执行结束);}});cached.shutdown();}
}以上代码运行报错 可以看到虽然调用线程持有锁对象但和调用wait的对象不一致仍然会报错java.lang.IllegalMonitorStateException ; 如何正常运行呢只要把LOCK_A和LOCK_B统一即可
正确用法
package com.suo.javacode.concurrent;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class WaitJoinTest {static ExecutorService cached Executors.newCachedThreadPool();static final String LOCK_A lock-a;static final String LOCK_B lock-b;public static void main(String[] args) throws InterruptedException {cached.execute(()-{synchronized (LOCK_A) {System.out.println(线程-Thread.currentThread().getName()开始执行);try {LOCK_A.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(线程-Thread.currentThread().getName()执行结束);}});cached.shutdown();System.out.println(主线程结束);}
}这里能调用成功因为当前执行线程拿到了LOCK_A的锁这里代码会一直等待下去可以设置时间等待指定时间后会自动唤醒也可以使用notify()方法
二、notify()
1. 源码都是本地方法 2. 作用
notify()唤醒任意一个当前锁对象上处于等待状态的线程线程被唤醒后开始竞争锁notifyAll() 唤醒当前锁对象上所有处于等待状态的线程被唤醒后开始竞争锁使用前提与wait()方法相同执行线程必须持有该对象的锁
3. 示例
package com.suo.javacode.concurrent;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class WaitJoinTest {static ExecutorService cached Executors.newCachedThreadPool();static final String LOCK_A lock-a;static final String LOCK_B lock-b;public static void main(String[] args) throws InterruptedException {for(int i0;i3;i) {cached.execute(()-{System.out.println(线程-Thread.currentThread().getName()开始执行并尝试获取锁);synchronized (LOCK_A) {try {Thread.sleep(1000);System.out.println(线程-Thread.currentThread().getName()进入等待并释放锁);LOCK_A.wait();System.out.println(线程-Thread.currentThread().getName()被唤醒同时拿到锁);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(线程-Thread.currentThread().getName()执行结束释放锁);}});}Thread.sleep(10000);for(int i0;i3;i) {synchronized (LOCK_A) {LOCK_A.notify();System.out.println(唤醒任一线程);}}//或者使用LOCK_A.notifyAll();cached.shutdown();System.out.println(主线程结束);}
}执行结果
三、Java源码中的实际使用join()
1. join源码 从源码可以看出join利用了wait方法来实现millis0时只要线程还在运行就会进入wait,等待millis时间结束或者线程结束方法才能结束millis0时只要线程没有执行完毕就会一直处于等待状态因为代码中有while循环notify唤醒后也会立即进入下一次wait(),直到线程运行结束或者等待时间到期
2. 作用
等待线程执行完成只有Thread对象有该方法
3. 示例 public static void main(String[] args) throws InterruptedException {Runnable r ()-{for(int i0;i10;i) {System.out.println(线程-Thread.currentThread().getName():i);}};Thread t1 new Thread(r);Thread t2 new Thread(r);t1.start();t2.start();t1.join();System.out.println(主线程等待t1执行结束:System.currentTimeMillis());t2.join();System.out.println(主线程等待t2执行结束:System.currentTimeMillis());System.out.println(主线程结束);}以上示例代码中的线程池仅作为测试使用绝对不能用于生产避免出现OOM;wait()和join()在实际使用中都需要设置时间避免出现无法唤醒的状况从而造成OOM;实际使用中推荐使用CountDownLatch来代替join,使用join时无法使用线程池 四、sleep和wait的异同 相同点 都能让当前执行线程进入阻塞 不同点 1. sleep是Thread独有的静态方法 ,wait所有对象都有该方法2. sleep必须设置时间wait可以不设置且wait可以被notify唤醒3. sleep没有使用前提wait必须持有对象锁4. sleep不会释放执行线程持有的锁对象wait会释放锁