V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
coderstory
V2EX  ›  Java

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

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

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

    现在主线程创建了子线程并调用了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  
       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   ·   我们的愿景   ·   实用小工具   ·   5242 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 47ms · UTC 07:30 · PVG 15:30 · LAX 00:30 · JFK 03:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.