一、超类 Object 类 使用 native code 实现的 线程之间的 通信是怎样的?
二、源码注解
notify (1)这个线程 正在 等待 对象的监视器 (2)被唤醒
wait (1) 这个线程等待 (2)直到被通知 或 程序抛错
notifyAll (1)一组线程正在 等待 对象的监视器 (2)都被唤醒
/**
*
*/
public class NotifyTest {
public static class NotifyThread extends Thread{
public NotifyThread( String name , Runnable runnable ){
super( runnable, name );
}
}
public static class NotifyAllThread extends Thread{
public NotifyAllThread( String name , Runnable runnable ){
super( runnable,name);
}
}
public static class WaitThread extends Thread{
public WaitThread( String name , Runnable runnable ){
super( runnable,name);
}
}
public static class RunableSyncTest implements Runnable{
@Override
public void run() {
synchronized ( this ){
try {
System.out.println(" thread is waiting before :"+ Thread.currentThread().getName() );
super.wait();
System.out.println(" thread is waiting after "+ Thread.currentThread().getName() );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Runnable runnable = new RunableSyncTest();
NotifyAllThread allThread = new NotifyAllThread("all", runnable);
NotifyThread notifyThread = new NotifyThread("notify", runnable);
WaitThread waitThread = new WaitThread("wait", runnable);
allThread.start();
notifyThread.start();
waitThread.start();
}
}
代码结果
/***
thread is waiting before :all
thread is waiting before :notify # 加锁了,为什么 这个线程进来了?
thread is waiting before :wait # 为什么没有继续向下执行?
***/
先看测试代码(知道的浅,只能从Java 代码级别发生的情况确定,牛人看c)
1、wait() 等待的表现是?释放了当前的锁,进入 线程等待队列,直到被这个队列的某一个线程通知,才能继续获得锁。
2、三个线程一直都处于等待中,没有谁来通知。
3、一定得是 当前对象的锁,才能调用当前对象的wait(),notify(),notifyAll();
在这里 加锁 的对象是 this , 调用的是 this.wait(); 官方的要求是:只有获得对象的监视器,才能有“料”,去 wait(),去 通知
package notify;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
*/
public class NotifyTest {
public static class NotifyThread extends Thread{
public NotifyThread( String name , Runnable runnable ){
super( runnable, name );
}
}
public static class NotifyAllThread extends Thread{
public NotifyAllThread( String name , Runnable runnable ){
super( runnable,name);
}
}
public static class WaitThread extends Thread{
public WaitThread( String name , Runnable runnable ){
super( runnable,name);
}
}
public static class RunableSyncTest implements Runnable{
AtomicInteger integer = new AtomicInteger(0);
@Override
public void run() {
synchronized ( this ){
try {
System.out.println("before :["+ Thread.currentThread().getName()+"] count:"+ integer.addAndGet( 1 ) );
if( integer.get() % 2 > 0 ){
super.wait();
System.out.println("waiting ["+ Thread.currentThread().getName()+"]" );
}else{
super.notify();
System.out.println("go to notify ["+ Thread.currentThread().getName()+"]" );
}
System.out.println("after: [ "+Thread.currentThread().getName()+"]" );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Runnable runnable = new RunableSyncTest();
NotifyAllThread allThread = new NotifyAllThread("all", runnable);
NotifyThread notifyThread = new NotifyThread("notify", runnable);
WaitThread waitThread = new WaitThread("wait", runnable);
allThread.start();
notifyThread.start();
waitThread.start();
}
}
# 代码运行结果
before :[all] count:1 # all先获得锁
before :[wait] count:2 # all进入等待队列,释放了锁,
go to notify [wait] # wait线程抢到了锁,开始通知
after: [ wait] #
before :[notify] count:3
finally [all]
waiting [all]
after: [ all]
finally [notify]
waiting [notify]
after: [ notify]
总结:
(1)要想 使用 wait()\notify()这些方法,先得获取使用该对象的 监控器(锁),得加锁。
(2)wait(),使线程放弃锁,在原地进行了等待(应该是进入了 竞争该监控器的等待队列),被唤醒后,从原地开始执行(thread有自己的程序计数器)
(3)notify() | notifyAll() 当前拥有对象监控器的 开始释放锁,通知 等待队列
应用场合
(1)例如: netty 生成异步结果代码段,说是异步转同步,本质的该线程一直在等待结果,拿到结果后才返回。
@Override
public Promise<V> await() throws InterruptedException {
if (isDone()) {
return this;
}
if (Thread.interrupted()) {
throw new InterruptedException(toString());
}
checkDeadLock();
synchronized(this) { ## 对 this 进行加锁
while (!isDone()) { ## 当 结果还没有 完成
incWaiters(); ## 增加等待线程数;
try {
wait(); ## 该线程进入等待队列,(阻塞了)释放锁,另外一个线程进入
} finally {
decWaiters();## 被通知了,出队列,
}
}
}
return this;
}