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

2021-05-28 01:11:52 +08:00
 coderstory

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

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

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

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

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

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

用 while(true) sleep 来实现功能逻辑,目测毫无心智负担😂 还是自己写的代码浅显易懂😂
ChovyChu
2021-05-28 09:22:12 +08:00
打个 debug 把两个线程都阻塞了就可以了吧,想让哪个执行就往下走呗
fkname
2021-05-28 09:25:14 +08:00
我怎么记忆中是 notify 后不会释放锁,会继续执行啊?
GuuJiang
2021-05-28 09:46:13 +08:00
@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
2021-05-28 11:33:08 +08:00
notify 之后的代码会执行的,直到同步方法结束才让出锁
qwerthhusn
2021-05-28 11:35:15 +08:00
CompletableFuture
eric96
2021-05-28 11:45:48 +08:00
说句不好听的话:建议说下你的需求,想实现什么,而不是给出一个有缺陷的方案,然后来寻求解决的方法。就好像问题是 A,然后你想了一个可能挺奇怪的解决方案,但是有问题 B,然后问问题 B 怎么解决,但是其实很有可能问题 A 是有标准的解决方案的。
hhjswf
2021-05-28 12:35:56 +08:00
Condition
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) {

}
}
}
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/779689

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX