Java 尝试同步两个线程时遇到问题
我试图同步到两个线程,一个打印“ping”,另一个打印“pong”,以打印类似“ping-pong-pong-pong-pong….”的内容。我编写了以下程序来实现这一点,但无法获得预期的结果。我不知道我犯了什么错误。互联网上也有同样的解决方案,但我认为在寻找现成的答案之前,我应该自己试一试Java 尝试同步两个线程时遇到问题,java,multithreading,synchronized,Java,Multithreading,Synchronized,我试图同步到两个线程,一个打印“ping”,另一个打印“pong”,以打印类似“ping-pong-pong-pong-pong….”的内容。我编写了以下程序来实现这一点,但无法获得预期的结果。我不知道我犯了什么错误。互联网上也有同样的解决方案,但我认为在寻找现成的答案之前,我应该自己试一试 class MyThread implements Runnable{ String val = null; MyThread(String val) { this.val = val;
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
请告知我在这里犯了什么基本错误,以及是否有更好的方法来实现相同的行为。谢谢
在进行建议的更改后:我尝试使用wait/notify使用线程通信,但得到了非法的MonitorStateException。我猜我在获取锁定的对象上使用了wait/notify(在同步上下文中使用wait/notify)。请帮助我理解这个概念的微妙之处。塞纳克斯
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)
在你的
pintMessage
中,无论turn
的值是多少,你都会打印一些东西。在你的pintMessage中,无论turn
的值是多少,你都会打印一些东西。你把同步的概念弄错了
JVM确保始终只有进程在执行同步块,但它不控制请求进程,这意味着它只按照调用该块的顺序处理调用
在您的情况下:在JVM将循环设置为后台供另一个线程执行之前,每个线程都有机会多次执行循环
如果要确保特定顺序,必须使用wait()
和notify()
/notifyAll()
:
([编辑]:此代码可能无法正常工作(未测试),只是为了演示原理…)
有关mor信息,请参见此处您将同步的概念理解错误
JVM确保始终只有进程在执行同步块,但它不控制请求进程,这意味着它只按照调用该块的顺序处理调用
在您的情况下:在JVM将循环设置为后台供另一个线程执行之前,每个线程都有机会多次执行循环
如果要确保特定顺序,必须使用wait()
和notify()
/notifyAll()
:
([编辑]:此代码可能无法正常工作(未测试),只是为了演示原理…)
有关mor信息,请参见此处您得到了什么输出?嗨,我刚刚编辑了这个问题以反映获得的输出。谢谢printMessage
不能保证ping线程的圈数始终为1,而pong线程的圈数始终为2。就方法而言,圈数与当前执行的线程无关。要获得所需的输出,您需要找到一种在线程之间通信的方法,以便ping知道它的作用turn@conscells:如果你能建议一种方法,让ping线程知道是否轮到你了,那会很有帮助。我没有提到,因为你说你不想要一个现成的答案。但您可以研究线程信令或阻塞队列,以使多个线程协作。我也建议你去看看。你得到了什么输出?嗨,吓人的是,我刚刚编辑了这个问题,以反映获得的输出。谢谢printMessage
不能保证ping线程的圈数始终为1,而pong线程的圈数始终为2。就方法而言,圈数与当前执行的线程无关。要获得所需的输出,您需要找到一种在线程之间通信的方法,以便ping知道它的作用turn@conscells:如果你能建议一种方法,让ping线程知道是否轮到你了,那会很有帮助。我没有提到,因为你说你不想要一个现成的答案。但您可以研究线程信令或阻塞队列,以使多个线程协作。我也建议你去。
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();
}
}