java多线程协作

本文用一个生活中的例子(订阅-投送报纸)阐明多线程协作的问题。在java中,就是 wait/notify/synchronized的相关用法。

附带的代码既是一个测试案例,同时也是一个简单的“生产者-消费者”框架。如果使用此框架,用户只需实现自己的 生产过程、消费过程、产品的取放,框架代码已经实现 生产-消费 线程间的协作,参考代码中test包。地址:生产-消费 多线程代码

线程间协作

多个线程可以协作完成一项任务,比如典型的“生产-消费”问题,生产者线程负责创建一些产品(数据),消费者负责使用这些产品(数据)。

多线程协作可以保持生产者和消费者互相独立,各做各的事情,生产者只管生产,不管谁来消费以及如何消费,消费者也不管是谁来生产产品。这使得程序逻辑清晰简洁。

不过,无法避免的接触就是它们两者之间传递的产品,消费者必须确认产品已经生产出来才能开始消费,生产者通常也必须确认有足够的仓库容量来存放新生产的产品。因此必须采取某种机制来保证他们的工作不会出现混乱。

订阅和投送报纸的例子(“生产-消费”问题)

我们用订阅和投送报纸的例子来考虑这个问题。A订阅了一份报纸,邮递员B负责投递,但投递时间是不一定的。A希望尽快的拿到报纸,最好是B一完成投递就拿到报纸阅读。简单粗暴的方式是A反复的检查邮箱,看到报纸就拿走。但这样太辛苦了,绝大多数时候都是无效劳动。用计算机程序来做的话就是不断查询邮箱状态,很浪费CPU时间。

门铃(notifyAll, notify)

所以比较好的方法是安装一个专用门铃(专用的意思是只要铃响就意味着邮箱中肯定有报纸),A只需在房间休息(wait),当B投递报纸后按一下门铃(notifyAll, notify),A就知道出来拿报纸了。

但是可能出现两种问题。

一个是虚假门铃(spurious wakeups)。比如邻居小孩有点淘气,有时候会去乱按门铃。A这时出来就拿不到报纸。另一个是共用门铃(多个生产线程;多个消费线程;多种唤醒条件)。比如A家里夫妻两个(多个消费线程)都准备去拿报纸,门铃响了以后,A1去拿回报纸,A2再去就只是空邮箱了。

结果就是非专用门铃(即无法确保门铃是专用的,铃响不代表邮箱中一定有报纸)。不过解决办法也很简单,就是检查后再行动("check and act"),每次门铃响了以后,先检查邮箱,如果有报纸再拿回来,如果没有就继续回去休息。

时间差问题(多线程交错运行)

但是,检查后再行动引起了时间差问题。对于人来说打开邮箱拿报纸似乎是一件事情,但如果事先并不确定里面是否有报纸的话,检查 和 行动其实是两个步骤。时间差问题,比如这样的情况:A出来检查邮箱,发现没有报纸,于是决定回去休息,往回走的路上,邮递员到了,邮递员把报纸放进邮箱,按了门铃,但这时候A还在回房间的路上,并没有听见门铃响,也就不知道邮递员已经送来报纸,于是A按预定计划回房间休息,而邮递员已经走了,结果A错过了这份报纸。

如何解决呢?我们要确保A查看邮箱到回到房间这段时间内,邮递员不能进行投递。所以可以修建一个保护罩(synchronized),将邮箱和门口的道路("check and act")都笼罩在内,而保护罩同一时间只允许A或B之中的一个人进入。比如上面的情况,A进入保护罩查看邮箱,发现没有报纸后回去休息,这时邮递员B到达准备投递,但A还在保护罩里面,禁止B进入,B只好在外面等一下。等A离开保护罩回到房间,这时邮递员才能进入保护罩并投递报纸,然后按下门铃,而这时A已经在房间里了,肯定能听到铃声,就会出来拿报纸了。

小结

在java程序中,A休息用 wait() 实现,B按门铃用 notifyAll() 或 notify() 实现,邮箱的状态(有没有报纸)可以通过定义一个变量来表示,A检查该变量的值来决定是拿报纸还是回去休息。要使用 while循环检查变量状态("check and act")来避免虚假门铃和共用门铃的问题。保护罩用 synchronized关键字 实现,确保("check and act")成为一个原子操作。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    小徐andorid阅读 2,799评论 3 53
  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 8,981评论 0 13
  • 家塾班的课堂上姬老师说我在我执的状态里,我没有回应,是因为我看不见自己,就不相信。回来两天的时间,我...
    正心正行阅读 552评论 1 5
  • 终于任性的买了手机。家长真的被裹挟了。 接下来要怎么办怎么办?拟定了双方就手机购买后约定的数项事项。不知道成效如何...
    宇星晨1205阅读 126评论 0 0