为了账号安全,请及时绑定邮箱和手机立即绑定

原来 Java 线程还能这样“聊天”

标签:
Java JavaScript

原文来自于:https://zha-ge.cn/java/63

原来 Java 线程还能这样“聊天”

事情是这样的,前几天突然接了个需求,说要同时控制两个线程“你一句我一句”地输出内容。本来以为就是个同步问题,随便丢个synchronized就完事。结果真下手一弄,才发现没那么简单。这不,线程要是能像群聊似的直接互怼,那多有意思。但是现实……让人头秃。

那一天,我手贱想让线程聊个天

兄弟们,想象一下啊——有两个线程,一个负责输出“你好”,一个负责输出“世界”,目标是让它俩交替输出,组成梦想的“你好 世界 你好 世界……”。
理想很美好,现实嘛,一通瞎搅和。

我的第一反应就是直接用 synchronized,哼哼哈嘿上去就干,但很快我就怀疑人生:线程A刚“你好”,线程B已经“世界世界世界”地冲出去了……这群线程老是抢着说话,根本不懂排队。

所以,我开始试着让它们更“有礼貌”一些。找来Object的wait/notify,希望能分别喊“我说完了,该你了!”

代码长这样,核心是两人轮流:

synchronized (obj) {
    while (!shouldSpeak) obj.wait();
    System.out.print(msg);
    shouldSpeak = false;
    obj.notify();
}
// ...

逻辑上是不是听起来还挺靠谱?轮流喊人出场。但实战完全是另一个故事。

踩坑瞬间

麻了,真的麻了。

  • 有次两个线程谁都懒得动,现场安静得跟图书馆一样——死锁了。
  • 要么就是“你好你好你好……”连续串烧,B啥声音也没有,我以为世界线塌了。
  • 搞半天,原来notify不会随机叫醒合适的那个“同学”,经常自己把自己叫醒,活脱脱自言自语。

来,表格一眼看出几个经典“社死现场”:

场景 现象 心理阴影面积
notify错唤 一方连说多句 一桌拍掉手机
死锁 全部沉默、一片黑暗 凉凉
忘调布尔值 无限循环or不再发言 头微秃

有次一个同事路过,看我神情古怪,他瞄了眼代码就笑:“兄弟,你得注意顺序问题哇!”

探索到解决的坎坷路

我捣鼓半天,积攒的头发也快用尽了。要让线程像有聊头的朋友,得有组织有纪律啊!

后来直接用了ConditionReentrantLock组合,这才算分清彼此的“麦克风”。每说完一句,乖乖让对方接着说。

核心段子:

lock.lock();
try {
    while (!myTurn) condition.await();
    System.out.print(msg);
    myTurn = false;
    otherCondition.signal();
} finally {
    lock.unlock();
}

这回效果就很OK,就像配合得贼溜的相声演员——一句不多一句不少,绝不抢话。

经验启示

唉,折腾来折腾去,有几条感悟想和同行们叨咕:

  • 想让线程“互聊”,一定要有可靠的标志位,别指望notify随机分配发言权;
  • wait/notify容易踩坑,Condition配对更灵活(还可以设多个条件,不像大锅乱炖);
  • 别忘了try-finally安全解锁,否则寻人无果、锁永不见天日;
  • debug多看,死锁=新手开箱“彩蛋”;
  • 设计时想好场景,每回合切换,别让人自说自话。

最后,想想也挺有趣,线程“聊天”这活儿,其实还真得讲究点“社交礼仪”呢!


行了,今天的乱唠到此收尾,是不是感觉多线程也开始接地气了点?有什么踩坑瞬间,欢迎评论区“串门唠嗑”!

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消