gpt4 book ai didi

java - 尝试同步两个线程时遇到问题

转载 作者:行者123 更新时间:2023-12-01 21:15:40 25 4
gpt4 key购买 nike

我试图同步到两个线程,一个打印“ping”,另一个打印“pong”,打印类似“ping pong ping pong ping....”的内容,我编写了以下程序来实现这一目标,但无法得不到预期的结果。我想知道我犯了什么错误。互联网上可以找到相同的解决方案,但我认为在寻找现成的答案之前我应该​​自己尝试一下。

class MyThread implements Runnable{
String val = null;
MyThread(String val) {
this.val = val;
}

public void run() {
while(true){
PingPong.pintMessage(val);
}
}
}

public class PingPong {
static Integer turn = 1;

public static void main(String args []) {
Thread t1 = new Thread(new MyThread("ping"));
Thread t2 = new Thread(new MyThread("pong"));
t1.start();
t2.start();

}
public static void pintMessage(String msg) {
synchronized (turn) {
if(turn==1) {
System.out.println(Thread.currentThread().getName()+" "+msg);
turn=2;
}
else {
System.out.println(Thread.currentThread().getName()+" "+msg);
turn = 1;
}
}
}
}

输出:

Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong

请告诉我我在这里犯了什么基本错误,以及是否有更好的方法来实现相同的行为。谢谢!!

进行建议的更改后:我尝试使用等待/通知来使用线程通信,但收到 IllegalMonitorStateException。我想我已经在我正在获取锁定的对象上使用了等待/通知(在同步上下文中使用了等待/通知)。请帮助我理解这个概念的微妙之处。谢谢!

class MyThread implements Runnable{
String val = null;

MyThread(String val) {
this.val = val;
}

public void run() {
while(true){
try {
PingPong.printMessage(val);
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}
}

public class PingPong {
static Integer turn = 1;

public static void main(String args []) {
Thread t1 = new Thread(new MyThread("ping"));
Thread t2 = new Thread(new MyThread("pong"));
t1.start();
t2.start();
}
public static void printMessage(String msg) throws InterruptedException {
synchronized (turn) {
if(turn==1) {
System.out.println(Thread.currentThread().getName()+" "+msg);
turn=2;
}
else {
System.out.println(Thread.currentThread().getName()+" "+msg);
turn = 1;
}
turn.notifyAll();
turn.wait();
}
}
}

Output :
Thread-0 ping
Exception in thread "Thread-0" Thread-1 pong
java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at PingPong.printMessage(PingPong.java:40)
at MyThread.run(PingPong.java:12)
at java.lang.Thread.run(Unknown Source)

最佳答案

你对同步的概念理解错误了。

JVM 确保始终只有一个进程执行同步 block ,但它不控制排队进程,这意味着它只按照调用的顺序处理调用 block 。

在您的情况下:每个线程都有机会多次执行循环,然后 JVM 将其设置为后台以供另一个线程执行。

如果您想确保特定的顺序,则必须使用 wait()notify()/notifyAll():([编辑]:此代码可能无法正常工作(未经测试),它只是为了演示原理...)

class MyThread implements Runnable{
private Object other;
public void setOther (MyThread other){
this.other = other;

}
//no changes
while(true){
PingPong.pintMessage(val);
notifyAll();
other.wait();
}

}

public static void pintMessage(String msg) {
synchronized (turn) {
// no changes
// MyThread.semaphore.notifyAll();
}
}

请参阅此处了解更多信息 https://docs.oracle.com/javase/tutorial/essential/concurrency/

关于java - 尝试同步两个线程时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40212419/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com