Java并发15:Lock&Condition-2


Java并发15:Lock&Condition-2

Java代码默认同步处理。

通过两种方式实现异步:

  • 调用方创建一个子线程,在子线程方法中调用,即异步调用
  • 方法实现时,创建一个新线程执行主要逻辑,主线程直接return,即异步方法

Dubbo源码分析

RPC 调用,在 TCP 协议层面,发送完 RPC 请求后,线程不会等待 RPC 的响应结果。

但平常中的RPC调用大多是同步的,如Dubbo中的DefaultFuture.get()方法,就是帮忙做了异步转同步操作。

Dubbo中的DefaultFuture类的精简代码(2.7.3版本已不用lock和signal了)。

// 创建锁与条件变量
private final Lock lock = new ReentrantLock();
private final Condition done = lock.newCondition();

// 调用方通过该方法等待结果
Object get(int timeout){
  //记录请求发起时间
  long start = System.nanoTime();
  //锁定资源  
  lock.lock();
  try {
  //循环判断请求是否完成 MESA管程模型wait()范式
  //若未完成,就继续wait
  while (!isDone()) {
    //condition设置超时wait
    done.await(timeout);
    //记录当前执行时间
    long cur=System.nanoTime();
    //如果此时完成 或者 已超时 跳出循环
    if (isDone() || cur-start > timeout){
      break;
    }
  }
  } finally {
  		lock.unlock();
  }
  //未完成抛异常  
  if (!isDone()) {
  	throw new TimeoutException();
  }
  //完成后返回请求完成的结果
  return returnFromResponse();
}
// RPC结果是否已经返回
boolean isDone() {
  return response != null;
}
// RPC结果返回时调用该方法   
private void doReceived(Response res) {
  lock.lock();
  try {
    response = res;
    //这边check done!=null 没必要 done必不为空
    if (done != null) {
      //后来改成了signalAll();
      done.signal();
    }
  } finally {
    lock.unlock();
  }
}

别人的总结

DefaultFuture本质上只是一种future实现,所以理论上可以有多个线程同时持有同一个future并调用 get方法,如这时候使用signal()就有可能导致有些线程会请求超时

>DefaultFuture future = currentClient.request(inv, timeout);
>for(int i=0; i< 10000; i++) {
>new Thread(new Runnable() {
>@Override
>public void run() {
System.out.println(future.get().toString());
>}
>});
>}

——牧名


文章作者: Wendell
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Wendell !
评论
  目录