等待/通知机制
方法wait()的作用是使当前执行代码的线程进行等待。在调用wait()之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法。在执行wait()方法后,当前线程释放锁。
方法notify()也要在同步方法或同步块中调用,即在调用前,线程也必须获得该对象的对象级别锁。该方法用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则由线程规划器随机挑选出其中一个呈wait状态的线程,对其发出通知notify,并使它等待获取该对象的对象锁。需要说明的是,在执行notify()方法后,当前线程不会马上释放该对象锁,呈wait状态的线程也并不能马上获取该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁,而呈wait状态所在的线程才可以获取该对象锁。
方法notifyAll()可以使所有正在等待队列中等待同一共享资源的“全部”线程从等待状态退出,进入可运行状态。此时,优先级最高的那个线程最先执行,但也可能似乎随机执行,这要取决于JVM虚拟机的实现。
当interrupt()遇上wait()
当线程呈wait()状态时,调用线程对象的interrupt()方法会出现InterruptedException异常,锁也会被释放。
wait(long)
带一个参数的wait(long)方法的功能是等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。
join
在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程往往早于子线程结束之前结束。这时,如果主线程想等待子线程执行完成之后再结束,比如子线程处理一个数据,主线程要取得这个数据中的值,就要用到join()方法。方法join()的作用是等待线程对象销毁。
方法join具有使线程排队运行的作用,有些类似同步的运行效果。join与synchronized的区别是:join在内部使用wait()方法进行等待,而synchronized关键字使用的是“对象监视器”原理做为同步。
在join过程中,如果当前线程对象被中断,则当前线程出现异常。
join(long)中的参数是设定等待的时间。
join(long)与sleep(long)的区别
方法join(long)的功能在内部是使用wait(long)方法来实现的,所以join(long)具有释放锁的特点。而sleep(long)方法不会释放锁。