【C 语言难点突破】动态内存知识详解
join 的实现原理代码示例
源码分析
我们可以看出如果 join 给定的时间小于 0 就抛出异常
如果给定的时间为 0,其实也就是不加参数的 join,他就会判断是否 isAlive 也就是判断调用 join 的线程是否存活,如果存活则 wait(0)即一直等待,注意这里的 wait 是让 t1.join 同步的线程等待 t1 线程运行。举一个例子就是在 main 线程运行 t1.join(),那么 isAlive 判断的是 t1 线程是否存在,wait(0)是让 main 线程进行等待
如果给定的时间大于 0,那么这里的代码就和我们的上一篇内容里的保护性暂停扩展-增加超时 一模一样了,这里就是 保护性暂停 这个设计模式的体现
join 方法整体就是 保护性暂停 设计模式 的体现,只不过它没有传递数据 只是用来让其他线程陷入等待 使其调用 join 的线程可以先执行
扩展方面 解耦等待与成产
基本介绍
这个图中 t0 t2 t4 是寄信人线程,t1 t3 t5 负责邮递员线程 负责送信与代写信。每个信都有自己的 id 与内容 id 可以理解为收信人的地址,寄信人通过邮递员把新送给收信人,这里我们只研究寄信人与邮递员之间的消息传递。注意:一个邮递员只能寄一封信。
为什么要这样设计
这样设计的好处是解耦 也就是降低消息传递的复杂度与关联度,我们把 Futures 当做邮局 寄信人 把信给邮局 然后邮递员来取信送出,我们可以想象一下 如果没有这个邮局 我们会怎么样?我们需要亲自跑到邮递员家里 把信给他 这期间邮递员可能有事出门了 你就白去了 总之这样做 效率很低,这就是邮局的好处。
代码示例
结果:
12:21:51.157 c.People [Thread-1] - 开始寄信 id:312:21:51.158 c.People [Thread-0] - 开始寄信 id:112:21:51.157 c.People [Thread-2] - 开始寄信 id:212:21:52.171 c.Postman [Thread-4] - 送信 id:2, 内容:内容 212:21:52.171 c.Postman [Thread-5] - 送信 id:1, 内容:内容 112:21:52.171 c.Postman [Thread-3] - 送信 id:3, 内容:内容 312:21:52.171 c.People [Thread-0] - 寄信的内容 id:1, 内容:内容 112:21:52.171 c.People [Thread-2] - 寄信的内容 id:2, 内容:内容 212:21:52.171 c.People [Thread-1] - 寄信的内容 id:3, 内容:内容 3
解释与分析:
我们可以看出 我们寄信后每个信 都有一个对应的 邮递员来送信 信的内容与 id 也一致
我们首先关注到了几个类分别是:GuardedObject
GuardedObject 类是写入消息与获取消息的类,由于信是邮递员代写 所以邮递员写信就是写入消息 收信人得到信就是获取消息这个类有几个方法:getId:获取这个信的 idget:获取这个信,有时限的等待,如果获取时间过长就放弃获取 complete:写信
Mailboxes
Mailboxes 类 可以理解为邮局 负责解耦寄信人与邮递员,主要形式是通过 id 与信之间的一一对应实现,邮递员不需要知道寄信的是谁 他只需要关注他要寄到的地址(就是信的 id)是什么。这个类有几个方法与成员变量:boxes 变量:是一个 Hashtable 类型 因为 Hashtable 是线程安全的 所以不用考虑关于 用到有关 Hashtable 的方法的线程安全问题,Hashtable 的 key 是 id value 是信,我们通过 id 找到信 generateId 方法:作用是生产信的 id,在 createGuardedObject 创建信时被调用 getGuardedObject 方法:作用是邮递员通过 id 获取信 然后邮递员送信 因为已经送信了 所以我们需要把它的 Hashtable 删除,所以我们这里选择使用的方法是 boxes.remove(id); 通过 remove 获取信 并且删除它的 HashtablecreateGuardedObject 方法:作用是创建一封信 也就是一个 Hashtable,可以理解为寄信人 要寄信 需要先创建一个信封并且在信封上写上地址(id)getIds 方法:这个方法的作用是获取所有 id,目的是 让邮递员选择一个 id 对应的信送出
Postman
Postman 线程类 是邮递员类,作用是送信和代写信这个类有几个方法与成员变量:id 变量:要送信的 idmail 变量:要送信的内容 Postman:有参构造,参数为 id mail,通过 id 获取到信(内容为空) 然后往其中写入内容 mailrun 方法:作用为每个线程 都在 run 方法 中 通过 id 获取信 并且写入内容 mail
People
People 线程类 是寄信人类,作用是 创建信这个类的方法:run 方法:作用是创建信,并 在一段时间后 获取信的内容,如果 5s 后仍然没有获取到则放弃获取 说明信的内容写入超时
Test20
Test20 类是入口类创建了 3 个 People 线程与 3 个 Postman 线程,并且在 People 线程运行 1s 后 Postman 线程开始运行,模拟 1s 后送信到邮局
版权声明: 本文为 InfoQ 作者【Geek_65222d】的原创文章。
原文链接:【http://xie.infoq.cn/article/518980693185dca9ccb34fd59】。未经作者许可,禁止转载。
评论