深夜求助 Java 中 2 个线程怎么互相唤醒和挂起 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
coderstory
V2EX    Java

深夜求助 Java 中 2 个线程怎么互相唤醒和挂起

  •  
  •   coderstory
    coderstory 2021-05-28 01:11:52 +08:00 3195 次点击
    这是一个创建于 1665 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设现在有一个子线程和一个主线程

    现在主线程创建了子线程并调用了start方法 主线程挂起 子线程可能执行了几行代码就挂起了并唤醒了主线程 然后主线程执行了几行代码并挂起和唤醒子线程 ....如此循环

    子线程每执行一些任务就挂起并退回到主线程

    这个东西是目的是实现前端调试后端代码。。。后端的代码,可能是某个方法内存在几个断点,到了断电就要暂停,并把当前状态返回到前端,然后由前端决定是否往下走。到了代码里就是主线程控制子线程的代码是否往下走,断点的地方就需要 wait,并唤醒主线程把数据发前端

    目前尝试 wait 和 notify  但是子线程 notify 主线程后,自己还怎么 wait 暂停? 两个线程我用了同一个锁,子线程 notify 后锁就不在子线程了 这个时候 wait 就会异常

    14 条回复    2021-05-28 14:29:13 +08:00
    maninfog
        1
    maninfog  
       2021-05-28 01:26:48 +08:00
    用公平锁或者类似于 BlockingQueue 这样的生产者消费者模型去实现应该不难吧
    yujincheng08
        2
    yujincheng08  
       2021-05-28 01:36:16 +08:00
    子线程给主线程一个 countdown latch 然后等。主线程处理完就去 countdown 掉重新激活子线程。
    而主线程搞个消息队列一直等子线程发 countdown latch 就行。
    coderstory
        3
    coderstory  
    OP
       2021-05-28 02:13:51 +08:00
    @maninfog 主要是子线程被唤醒的时机是前端决定的 所以子线程需要暂停才行
    不能主线程走完子线程走,子线程走完主线程走.
    tongqe
        4
    tongqe  
       2021-05-28 07:39:02 +08:00
    locksupport 这玩意儿不就是干这的嘛
    XiLemon
        5
    XiLemon  
       2021-05-28 08:28:41 +08:00 via iPhone
    notify 只是把其他等待锁的线程唤醒,重新参与锁的竞争,并没有释放锁,wait 才会正真的释放锁
    xiangyuecn
        6
    xiangyuecn  
       2021-05-28 08:56:19 +08:00
    弃用 wait 、notify

    用 while(true) sleep 来实现功能逻辑,目测毫无心智负担 还是自己写的代码浅显易懂
    ChovyChu
        7
    ChovyChu nbsp;
       2021-05-28 09:22:12 +08:00
    打个 debug 把两个线程都阻塞了就可以了吧,想让哪个执行就往下走呗
    fkname
        8
    fkname  
       2021-05-28 09:25:14 +08:00
    我怎么记忆中是 notify 后不会释放锁,会继续执行啊?
    GuuJiang
        9
    GuuJiang  
       2021-05-28 09:46:13 +08:00 via iPhone   3
    @coderstory 我来帮你翻译下你的问题吧
    你的意思无非就是 B 唤醒 A 以后自己并不是马上进入 wait,而是继续执行,由别的条件来让 B 进入 wait,这段时间 A 和 B 是同时执行的,由此可以推论所有只用一把锁(此处指广义的锁,无论是 synchronized 、j.u.c.Lock 、单 Lock 多 Condition 等)的方案通通都是不可行的,这些方案实现的两个线程互相唤醒的效果从时间线上看都是交替执行,这里顺便纠正一下你以及楼里部分人对 wait/notify 的一个常见误解,并不是说 B 调了 notify/notifyAll 以后 A 就开始执行了,B 调 notify 仅仅是让 A 开始进入锁的竞争,直到 B 进入 wait 、或者结束执行等其它方式离开临界区,A 成功竞争到锁后才真正开始执行的
    回到你的问题来,再结合你下面说的应用场景,我觉得这大概率是个 XY 问题,先不说“前端调试后端”这个是否有误入歧途,光说前面这个问题,站在 B 的角度,从宏观上来说,你真的关心在 B 从调了 notify 到 wait 的这段时间 A 是不是真的开始执行了吗?这个对 B 来说理应是作为黑盒无感知的才对,如果你对这个有刚需,非要他们有一段并行的时间,那么一定是哪里出了问题,不要继续花心思在解决 Y 问题上了
    sankemao
        10
    sankemao  
       2021-05-28 11:33:08 +08:00 via iPhone
    notify 之后的代码会执行的,直到同步方法结束才让出锁
    qwerthhusn
        11
    qwerthhusn  
       2021-05-28 11:35:15 +08:00
    CompletableFuture
    eric96
        12
    eric96  
       2021-05-28 11:45:48 +08:00   3
    说句不好听的话:建议说下你的需求,想实现什么,而不是给出一个有缺陷的方案,然后来寻求解决的方法。就好像问题是 A,然后你想了一个可能挺奇怪的解决方案,但是有问题 B,然后问问题 B 怎么解决,但是其实很有可能问题 A 是有标准的解决方案的。
    hhjswf
        13
    hhjswf  
       2021-05-28 12:35:56 +08:00
    Condition
    jeffh
        14
    jeffh  
       2021-05-28 14:29:13 +08:00
    最简单的使用信号量吧,Semephore 就可以了,wait, notify 也可以的,你可能不理解这两个方法。notify 调用后并不会释放锁,需要等到 wait 或者 sychronized 结束。下面这段代码就能实现互相等待,输出结果是“1 one 2 two 3 three”
    ```java
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;

    @SpringBootApplication
    @Slf4j
    public class DemoApplication implements CommandLineRunner {

    Object lock = new Object();

    public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
    System.out.println("1");
    new Thread(() -> stop()).start();
    pause();
    System.out.println("2");
    pause();
    System.out.println("3");
    pause();
    }

    public void stop() {
    System.out.println("one");
    pause();
    System.out.println("two");
    pause();
    System.out.println("three");
    }

    public void pause() {
    try {
    synchronized (lock) {
    lock.notifyAll();
    lock.wait();
    }
    }catch (Exception e) {

    }
    }
    }
    ```
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1296 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 17:08 PVG 01:08 LAX 09:08 JFK 12:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86