c# await和wait的区别别

await和wait的区别与用法await和wait这两个词的意思基本相同,用法上有什么不同呢?这两个词的有什么具体的差别呢?能举例并详细说明一下吗?谢谢了_百度作业帮
await和wait的区别与用法await和wait这两个词的意思基本相同,用法上有什么不同呢?这两个词的有什么具体的差别呢?能举例并详细说明一下吗?谢谢了
await和wait的区别与用法await和wait这两个词的意思基本相同,用法上有什么不同呢?这两个词的有什么具体的差别呢?能举例并详细说明一下吗?谢谢了
两个词都是动词,等待.await是及物动词,后面直接加名词或代词作宾语.wait是不及物动词,一般与for连用,后面接宾语.当前访客身份:游客 [
自由而无用的灵魂
:你这个测试根本就不对,上Linux试试看,把交换S...
:protected void readData(SelectionKey key) thr...
:这里producer当前0.8.2版本已经没有zk.connect配...
:这个版本已经很早了啊
:引用来自“rxin”的评论 引用来自“Fra...
:看看这些评论,我只想说,国人对自己人太刻薄了。...
:楼主,您好,请问下,如使用mina作为服务端程序,...
:引用来自“無忌”的评论状态机是干嘛的,感觉有点...
:太棒了,博主辛苦
:请问楼主 ,用的是kafka哪个版本, 初学,感觉k...
今日访问:213
昨日访问:219
本周访问:803
本月访问:855
所有访问:142672
Mina源码阅读笔记(六)—Mina异步IO的实现IoFuture
发表于3年前( 19:25)&&
阅读(5372)&|&评论()
0人收藏此文章,
IoFuture是和IoSession紧密相连的一个类,在官网上并没有对它的描述,因为它一般不会显示的拿出来用,权当是一个工具类被session所使用。当然在作用上,这个系列可并不简单,我们先看源码的注释对它的描述:
IoFuture represents the completion of an asynchronous I/O operation on an IoSession.
这个类是提供异步操作的一个工具,所以在读源码之前,必须对异步IO操作有所了解,然后我们才可以顺着这条路往下走。关于异步IO的介绍可以看:
IoFuture通过IoFutureListener被IoSession绑定,它的实现都放在org.apache.mina.core.future下。在IoFuture的实现中,分别提供了读、写、连接、关闭的future,通过这四个future来实现异步操作。异步操作很重要的一部分就是对线程的控制,所以在IoFuture这个接口中,我们能很清楚的理清这几个方法:await、join。当然还有notify,但是notify没有必要写在接口中,它可以在程序里直接使用。
这个系列的类设计的很规整,从上图的结构就能看出来,图中省略了write和connection的图,它们分别和read与close一致。由于这个类的操作没有那么复杂,继承关系也没有那么多层,所以这里面都没有用到Abstract的类来做具体实现。
下面我们来看这里面最核心的一个类DefaultIoFuture。这个类实现IoFuture接口,主要实现了对await和join的操作,以及处理死锁的操作。我们先看这个类关联到的成员变量,都比较简单:
/** A number of seconds to wait between two deadlock controls ( 5 seconds ) */
private static final long DEAD_LOCK_CHECK_INTERVAL = 5000L;
/** The associated session */
private final IoS
/** A lock used by the wait() method */
private final O
private IoFutureListener&?& firstL
private List&IoFutureListener&?&& otherL
在我看来,读源码的目的,一是为了理清框架的设计逻辑,理清结构,学习这些关联关系;二是为了学习处理细节,比如死锁的处理、线程安全的处理。在这个类中,我们将看到mina作者是如何处理死锁的问题的。
我们先看await操作,await主要是为了等待异步操作的完成,然后通知相关的listener。我们先看一个简单的await操作和验证死锁的操作:
public IoFuture await() throws InterruptedException {
synchronized (lock) {
while (!ready) {
waiters++;
lock.wait(DEAD_LOCK_CHECK_INTERVAL);
} finally {
waiters--;
if (!ready) {
checkDeadLock();
我们应该要注意下在await方法中的wait操作,这里讲些题外话,面试中常问的wait和sleep的区别。wait的操作其实很规范,必须写在synchronized块内,必须由其他线程来notify,同时wait释放锁,不占资源。而sleep占着cup的资源区睡眠,时间没到不能被唤醒,只能通过中断来打断。在这个await方法中,wait了check dead lock的时间,并且设置了计数器waiters。这个waiters在setValue方法中被运用到,在setValue中:
public void setValue(Object newValue) {
synchronized (lock) {
// Allow only once.
if (ready) {
result = newV
if (waiters & 0) {
lock.notifyAll();
notifyListeners();
异步操作是没有一个固定的顺序,谁先做好谁就返回,所以一旦有异步任务完成了操作,就会notify所有的等待,让接下来先抢到的线程再执行。在DefaultIoFuture这个类中,我觉得最重要的到不是连接或者读写,而是上面提到的setValue和getValue,因为在后续的继承关系中,会不断的用到这两个方法。不仅在后续的继承关系中,这两个方法真正在传递值得操作是发生在IoService中,不要忘了虽然session很重要,但真正起连接作用的还是service。
然后我们再看下上面提到的check dead lock的方法,在抢占中只有读、写和连接会产生死锁的情况:
private void checkDeadLock() {
if (!(this instanceof CloseFuture || this instanceof WriteFuture || this instanceof ReadFuture || this instanceof ConnectFuture)) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
// Simple and quick check.
for (StackTraceElement s : stackTrace) {
if (AbstractPollingIoProcessor.class.getName().equals(s.getClassName())) {
IllegalStateException e = new IllegalStateException(&t&);
e.getStackTrace();
throw new IllegalStateException(&DEAD LOCK: & + IoFuture.class.getSimpleName()
+ &.await() was invoked from an I/O processor thread.
& + &Please use &
+ IoFutureListener.class.getSimpleName() + & or configure a proper thread model alternatively.&);
// And then more precisely.
for (StackTraceElement s : stackTrace) {
Class&?& cls = DefaultIoFuture.class.getClassLoader().loadClass(s.getClassName());
if (IoProcessor.class.isAssignableFrom(cls)) {
throw new IllegalStateException(&DEAD LOCK: & + IoFuture.class.getSimpleName()
+ &.await() was invoked from an I/O processor thread.
& + &Please use &
+ IoFutureListener.class.getSimpleName()
+ & or configure a proper thread model alternatively.&);
} catch (Exception cnfe) {
在追踪堆栈信息时,这里采用了两种check方式,简单和精确。在简单检测中,只是对比了类名,也就是对当前类有效,是一个一对一的比较。而在精确的检测中,采用isAssignableFrom方法来分别和其父类和本类进行比较。如果有死锁,就抛异常。另外join方法被废弃,由awaitUninterruptibly代替,虽然叫join,其实还是一种wait操作,等到一定时间将flag转变一下。
下面我们看ReadFuture接口,这个接口直接继承IoFuture接口,并添加了相关的写操作。接口由DefaultReadFuture实现。在使用中,ReadFuture在IoSession中read方法中被使用,也可以说,在session层,直接读写的是future,我们再看下AbstractIoSession中的read代码:
public final ReadFuture read() {
if (!getConfig().isUseReadOperation()) {
throw new IllegalStateException(&useReadOperation is not enabled.&);
Queue&ReadFuture& readyReadFutures = getReadyReadFutures();
synchronized (readyReadFutures) {
future = readyReadFutures.poll();
if (future != null) {
if (future.isClosed()) {
// Let other readers get notified.
readyReadFutures.offer(future);
future = new DefaultReadFuture(this);
getWaitingReadFutures().offer(future);
每次都是从队列中拿出一个future,同理,每次写也是往队列里写入一个future。在DefaultReadFuture中的方法都比较简单,这里就不贴出来了。另外WriteFuture和DefaultWriteFuture和read类似,也不再赘述。
最后我们看看ConnectFuture,我们常常写这么一段话来拿到session:
ConnectFuture future = connector.connect(new InetSocketAddress(
HOST, PORT));// 创建连接
future.awaitUninterruptibly();// 等待连接创建完成
session = future.getSession();// 获得session
提一点,在多态的使用上,ConnectFuture完全可以换成IoFuture,这对后面的代码没有一点儿影响,getSession本身就是继承自IoFuture的。ConnectFuture接口由DefaultConnectFuture来具体实现,由于继承了DefaultIoFuture,所以这里面用到最多的就是DefaultIoFuture中的setValue和getValue方法,上面我们也特别强调了这两个方法的重要性,通过对result(setValue)的传递实现了对session、exception等状态的传递。
稍微总结一下future对异步的贡献,官方对future的描述就是处理了异步操作,从源码中我们很明显的可以看到future是通过await和notify来控制操作的连续性,通过死锁检测来做wait时的保障,上层(session)通过队列来缓冲各种任务,然后通过竞争,谁抢到了线程,谁就执行。Future不难,组织结构也很清楚,我觉得看这节的源代码最主要的还是要做好两点,第一是搞懂什么是异步,第二是要明白future为异步贡献了什么。
下一篇就要讲mina中最庞大的filter chain了,这是mina中代码最多,也是最具特色的一部分。
更多开发者职位上
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读await.wait 不同_百度作业帮
await.wait 不同
await.wait 不同
await是及物动词,后直接跟名词或代词,等于wait不及物,单独用时常用wait to do sth,不能说await sb to do,可说wait for sb to do.
await及物wait不及物,与FOR连用java并发控制:ReentrantLock Condition使用详解 - 为程序员服务
为程序员服务
java并发控制:ReentrantLock Condition使用详解
java的java.util.concurrent.locks包内有Condition接口,该接口的官方定义如下:
Condition factors out the Object monitor methods (,
and ) into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitrary
implementations. Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.
Conditions (also known as condition queues or condition variables) provide a means for one thread to suspend execution (to "wait") until notified by another thread that some state condition may now be true. Because access to this shared state information occurs in different threads, it must be protected, so a lock of some form is associated with the condition. The key property that waiting for a condition provides is that it atomically releases the associated lock and suspends the current thread, just like Object.wait.
我们通过一个实际的例子来解释Condition的用法:
我们要打印1到9这9个数字,由A线程先打印1,2,3,然后由B线程打印4,5,6,然后再由A线程打印7,8,9. 这道题有很多种解法,现在我们使用Condition来做这道题(使用Object的wait,notify方法的解法在)。
package cn.outofmemory.
import java.util.concurrent.locks.C
import java.util.concurrent.locks.L
import java.util.concurrent.locks.ReentrantL
public class App {
static class NumberWrapper {
public int value = 1;
public static void main(String[] args) {
//初始化可重入锁
final Lock lock = new ReentrantLock();
//第一个条件当屏幕上输出到3
final Condition reachThreeCondition = lock.newCondition();
//第二个条件当屏幕上输出到6
final Condition reachSixCondition = lock.newCondition();
//NumberWrapper只是为了封装一个数字,一边可以将数字对象共享,并可以设置为final
//注意这里不要用Integer, Integer 是不可变对象
final NumberWrapper num = new NumberWrapper();
//初始化A线程
Thread threadA = new Thread(new Runnable() {
public void run() {
//需要先获得锁
lock.lock();
System.out.println("threadA start write");
//A线程先输出前3个数
while (num.value &= 3) {
System.out.println(num.value);
num.value++;
//输出到3时要signal,告诉B线程可以开始了
reachThreeCondition.signal();
} finally {
lock.unlock();
lock.lock();
//等待输出6的条件
reachSixCondition.await();
System.out.println("threadA start write");
//输出剩余数字
while (num.value &= 9) {
System.out.println(num.value);
num.value++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
Thread threadB = new Thread(new Runnable() {
public void run() {
lock.lock();
while (num.value &= 3) {
//等待3输出完毕的信号
reachThreeCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
lock.lock();
//已经收到信号,开始输出4,5,6
System.out.println("threadB start write");
while (num.value &= 6) {
System.out.println(num.value);
num.value++;
//4,5,6输出完毕,告诉A线程6输出完了
reachSixCondition.signal();
} finally {
lock.unlock();
//启动两个线程
threadB.start();
threadA.start();
上述代码中有完整的注释,请参考注释,理解Condition的用法。
基本思路就是首先要A线程先写1,2,3,这时候B线程应该等待reachThredCondition信号,而当A线程写完3之后就通过signal告诉B线程“我写到3了,该你了”,这时候A线程要等嗲reachSixCondition信号,同时B线程得到通知,开始写4,5,6,写完4,5,6之后B线程通知A线程reachSixCondition条件成立了,这时候A线程就开始写剩下的7,8,9了。
为了更好的理解Condition的用法,我们再看下java官方提供的例子:
import java.util.R
import java.util.concurrent.locks.C
import java.util.concurrent.locks.L
import java.util.concurrent.locks.ReentrantL
public class AppOfficial {
* BoundedBuffer 是一个定长100的集合,当集合中没有元素时,take方法需要等待,直到有元素时才返回元素
* 当其中的元素数达到最大值时,要等待直到元素被take之后才执行put的操作
* @author yukaizhao
static class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr,
public void put(Object x) throws InterruptedException {
System .out.println("put wait lock");
lock.lock();
System.out.println("put get lock");
while (count == items.length) {
System.out.println("buffer full, please wait");
notFull.await();
items[putptr] =
if (++putptr == items.length)
putptr = 0;
notEmpty.signal();
} finally {
lock.unlock();
public Object take() throws InterruptedException {
System.out.println("take wait lock");
lock.lock();
System.out.println("take get lock");
while (count == 0) {
System.out.println("no elements, please wait");
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length)
takeptr = 0;
notFull.signal();
} finally {
lock.unlock();
public static void main(String[] args) {
final BoundedBuffer boundedBuffer = new BoundedBuffer();
Thread t1 = new Thread(new Runnable() {
public void run() {
System.out.println("t1 run");
for (int i=0;i&1000;i++) {
System.out.println("putting..");
boundedBuffer.put(Integer.valueOf(i));
} catch (InterruptedException e) {
e.printStackTrace();
Thread t2 = new Thread(new Runnable() {
public void run() {
for (int i=0;i&1000;i++) {
Object val = boundedBuffer.take();
System.out.println(val);
} catch (InterruptedException e) {
e.printStackTrace();
t1.start();
t2.start();
这个示例中BoundedBuffer是一个固定长度的集合,这个在其put操作时,如果发现长度已经达到最大长度,那么会等待notFull信号,如果得到notFull信号会像集合中添加元素,并发出notEmpty的信号,而在其take方法中如果发现集合长度为空,那么会等待notEmpty的信号,同时如果拿到一个元素,那么会发出notFull的信号。
推荐阅读:
相关聚客文章}

我要回帖

更多关于 wait和await 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信