我正在尝试同步三个线程来打印012012012012 ....但它无法正常工作。为每个线程分配一个号码,当它从主线程接收到信号时,它会打印该号码。以下程序有问题,我无法捕捉到。
public class Application {
public static void main(String[] args) {
int totalThreads = 3;
Thread[] threads = new Thread[totalThreads];
for (int i = 0; i < threads.length; i++) {
threads[i] = new MyThread(i);
threads[i].start();
}
int threadIndex = 0;
while (true) {
synchronized(threads[threadIndex]) {
threads[threadIndex].notify();
}
threadIndex++;
if (threadIndex == totalThreads) {
threadIndex = 0;
}
}
}
}
class MyThread extends Thread {
private int i;
public MyThread(int i) {
this.i = i;
}
@Override
public void run() {
while (true) {
synchronized(this) {
waitForSignal();
System.out.println(i);
}
}
}
private void waitForSignal() {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:3)
您需要更多协调。 notify
调用不会立即唤醒线程并强制它继续。相反,可以将notify
视为向线程发送电子邮件,让它知道它可以继续。想象一下,如果你想让你的3个朋友按顺序给你打电话。你给朋友1发了一封电子邮件给你打电话,等了一秒钟,发了一封电子邮件给朋友2,等了一秒钟,然后发了一封邮件给朋友3.你认为你会按照确切的顺序打电话吗?
添加更多协调的一种方法是使用一些共享状态来指示它的转向。如果你所有的朋友都可以看到你的房子,你可以在房子的外面放一个号码,表明轮到他们打电话了。每个朋友都会等到他们看到他们的号码,然后打电话。
答案 1 :(得分:0)
这是你的问题:
int threadIndex = 0;
while (true) {
synchronized(threads[threadIndex]) {
threads[threadIndex].notify();
}
threadIndex++;
if (threadIndex == totalThreads) {
threadIndex = 0;
}
}
主线程以正确的顺序通知所有线程。但是,您的线程是独立工作的。它们可能会或可能不会在特定时间点安排。因此最终结果可能是,线程2在线程1之前的线程1之前到达wait/print
锁定。最终的顺序不是由发送通知确定的,而是(实质上)由调度程序确定。
解决方案是以这种方式改变:
答案 2 :(得分:0)
另一种可能的解决方案:在主线程中,您可以在通知线程(在同一synchronized
块中)之后立即等待,如下所示:
synchronized (threads[threadIndex])
{
threads[threadIndex].notify();
threads[threadIndex].wait(); // try/catch here
}
在线程的run
方法中,您可以在线程完成其工作后使用notifyAll
唤醒主线程:
synchronized (this)
{
waitForSignal();
System.out.println(i);
notifyAll();
}
更复杂的解决方案将涉及java.util.concurrent.locks包中的类。
答案 3 :(得分:0)
package threads;
import java.util.concurrent.Semaphore;
public class ZeroEvenOddPrinter {
class Runner extends Thread{
Semaphore prev;
Semaphore next;
int num = 0;
public Runner(Semaphore prev,Semaphore next,int num){
this.prev = prev;
this.next = next;
this.num = num;
}
@Override
public void run(){
while (true) {
try {
Thread.sleep(100);
prev.acquire();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (num == 0)
System.out.println(0);
else {
System.out.println(num);
num = num + 2;
}
next.release();
}
}
}
static public void main(String args[]) throws InterruptedException{
Semaphore sem1 = new Semaphore(1);
Semaphore sem2 = new Semaphore(1);
Semaphore sem3 = new Semaphore(1);
ZeroEvenOddPrinter zeo = new ZeroEvenOddPrinter();
Runner t1 = zeo.new Runner(sem1,sem2,0);
Runner t2 = zeo.new Runner(sem2,sem3,1);
Runner t3 = zeo.new Runner(sem3,sem1,2);
sem1.acquire();
sem2.acquire();
sem3.acquire();
t1.start();
t2.start();
t3.start();
sem1.release();
}
}
这里我使用信号量作为所有三个线程的触发器。最初所有线程都将在sem1,sem2,sem3上被阻止。然后我将释放sem1并且第一个线程将执行然后它将释放第二个线程,依此类推......最好的部分是你将这个逻辑扩展到n个线程。祝你好运!!!