wait()、notify()和notifyAll()是Object类中的方法:
为什么wait()等方法是在Object中而不是Thread中呢?
同理,wait(),notify()是对等待这个Object(锁)的线程进行阻塞,唤醒等操作的,当然也要放在Object中
假设,wait(),notify()放在Thead中,那么Thread可能等待很多个锁,操作起来也很复杂
如果调用某个对象的wait()方法,当前线程必须拥有这个对象的monitor(即锁),因此调用wait()方法必须在同步块或者同步方法中进行(synchronized块或者synchronized方法)
调用某个对象的wait()方法,相当于让当前线程交出此对象的monitor,然后进入等待状态,等待后续再次获得此对象的锁(Thread类中的sleep方法使当前线程暂停执行一段时间,从而让其他线程有机会继续执行,但它并不释放对象锁)
同样地,调用某个对象的notify()方法,当前线程也必须拥有这个对象的monitor,因此调用notify()方法必须在同步块或者同步方法中进行(synchronized块或者synchronized方法)
进阶一信号量
Java 提供了经典信号量(Semaphore)的实现,通过控制一定数量的允许(permit)的方式,来达到限制通用资源访问的目的。 你可以想象一下这个场景,在车站、机场等出租车时,当很多空出租车就位时,为防止过度拥挤,调度员指挥排队,等待坐车的队伍一次进来5个人上车, 等这5个人坐车出发,再放进去下一批 当信号量的大小为1时,与synchronized没有区别
public class SemaphoreTest { private static Semaphore semaphore = new Semaphore(5); public static void main(String[] args) { for (int i = 0; i < 10; i++) { new CarWorker(semaphore).start(); } }}class CarWorker extends Thread { private Semaphore semaphore; public CarWorker(Semaphore semaphore) { this.semaphore = semaphore; } @Override public void run() { try { out.println(Thread.currentThread() + " waiting permitted"); semaphore.acquire(); out.println(Thread.currentThread() + " on car !"); Thread.sleep(10000); } catch (Exception e) { } finally { out.println(Thread.currentThread() + " release permitted"); semaphore.release(); } }}复制代码
进阶-CountDownLatch
一次性使用的计数器,当CountDownLatch中数值为0时,所有await的线程得到唤醒 特别适合于A线程需要等待B和C线程的结果作为参数的这种场景
public class CountDownLatchTest { public static void main(String[] args) { CountDownLatch countDownLatch = new CountDownLatch(6); for (int i = 0; i < 5; i++) { new FirstBatchPassenger(countDownLatch).start(); } for (int i = 0; i < 5; i++) { new SecondBatchPassenger(countDownLatch).start(); } while (countDownLatch.getCount() != 1) { try { Thread.sleep(1000); } catch (InterruptedException e) { } } out.println("MainThread countDown!"); countDownLatch.countDown(); }}class FirstBatchPassenger extends Thread { private CountDownLatch countDownLatch; public FirstBatchPassenger(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } @Override public void run() { out.println("FirstBatchPassenger Executed!"); countDownLatch.countDown(); }}class SecondBatchPassenger extends Thread { private CountDownLatch countDownLatch; public SecondBatchPassenger(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } @Override public void run() { try { countDownLatch.await(); out.println("SecondBatchPassenger Executed!"); } catch (InterruptedException e) { } }}复制代码
输出:
FirstBatchPassenger Executed!FirstBatchPassenger Executed!FirstBatchPassenger Executed!FirstBatchPassenger Executed!FirstBatchPassenger Executed!MainThread countDown!SecondBatchPassenger Executed!SecondBatchPassenger Executed!SecondBatchPassenger Executed!SecondBatchPassenger Executed!SecondBatchPassenger Executed!复制代码
进阶三-CyclicBarrier
触发屏障,当await自动达到屏障数量时,触发屏障操作。可重复使用!
public class CyclicBarrierTest { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> out.println("Action GO!")); for (int i = 0; i<6;i++){ new CyclicBarrierWorker(cyclicBarrier).start(); } }}class CyclicBarrierWorker extends Thread { private CyclicBarrier cyclicBarrier; public CyclicBarrierWorker(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; } @Override public void run() { out.println("Executed!"); try { cyclicBarrier.await(); } catch (InterruptedException e) { } catch (BrokenBarrierException e) { } }}复制代码
输出:
Executed!Executed!Executed!Action GO!Executed!Action GO!Executed!Executed!Action GO!复制代码