我有三个线程ThreadA,ThreadB和ThreadC分别在循环中打印值A,B和C。我希望输出像A,B,C一样,然后再像是A,B和C,直到在线程中执行循环。我想使用wait和notify编写此示例程序。下面的代码显示了所需的输出,但是有时我在输出中仅看到“ A”,无法弄清楚情况。
public class ThreadOrder {
public static void main(String[] args) {
Object lockAB = new Object();
Object lockBC = new Object();
Object lockCA = new Object();
Thread threadA = new Thread(new ThreadOrder().new ThreadA(lockAB, lockCA));
Thread threadB = new Thread(new ThreadOrder().new ThreadB(lockAB, lockBC));
Thread threadC = new Thread(new ThreadOrder().new ThreadC(lockBC, lockCA));
threadA.start();
threadB.start();
threadC.start();
}
class ThreadA implements Runnable {
Object lockAB;
Object lockCA;
public ThreadA(Object lockAB, Object lockCA) {
this.lockAB = lockAB;
this.lockCA = lockCA;
}
@Override
public void run() {
for(int i=0; i<3; i++) {
if(i!=0) {
try {
synchronized (lockCA) {
lockCA.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
synchronized (lockAB) {
lockAB.notify();
}
}
}
}
class ThreadB implements Runnable {
Object lockAB;
Object lockBC;
public ThreadB(Object lockAB, Object lockBC) {
this.lockAB = lockAB;
this.lockBC = lockBC;
}
@Override
public void run() {
for(int i=0; i<3; i++) {
try {
synchronized (lockAB) {
lockAB.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B");
synchronized (lockBC) {
lockBC.notify();
}
}
}
}
class ThreadC implements Runnable {
Object lockBC;
Object lockCA;
public ThreadC(Object lockBC, Object lockCA) {
this.lockBC = lockBC;
this.lockCA = lockCA;
}
@Override
public void run() {
for(int i=0; i<3; i++) {
try {
synchronized (lockBC) {
lockBC.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("C");
synchronized (lockCA) {
lockCA.notify();
}
}
}
}
}
您打电话给wait
,但尚未测试是否有等待的对象。您调用了notify
,但是您尚未更改通知另一个线程所需的任何内容。您具有所有这些synchronized
方法,但是没有共享状态要保护的同步。
代码中的任何内容都没有任何意义,并且似乎您从根本上不了解wait
/ notify
机制的作用。 wait
函数允许线程等待某些共享状态更改,notify
函数允许一个线程告诉其他线程某些共享状态已更改。但是必须有一些共享状态,因为wait
/ notify
机制(与锁或Sempahore不同)在内部是无状态的。
您可能应该具有一些受同步保护的共享状态。它应该编码下一个线程。如果您需要打印,但是共享状态表明该轮到您了,那么您需要进行一些操作wait
。当您进行打印并轮到另外一个线程打印时,那么您就可以notify
其他线程。
考虑通过阻塞队列来创建相互连接的线程环。然后,您可以在环上传递令牌。每个线程都在等待接收令牌,打印其输出,将令牌传递到环中的下一个线程,然后返回等待状态。
package com.test.algorithms;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
public class PrintInOrder {
private static Integer[] a = { 1, 1, 1 };
private static Integer[] b = { 2, 2, 2 };
private static Integer[] c = { 3, 3, 3 };
private static Integer[] d = { 4, 4, 4 };
public static void main(String[] args) throws InterruptedException {
QueueOrder q1 = null;
QueueOrder q2 = null;
QueueOrder q3 = null;
QueueOrder q4 = null;
q1 = new QueueOrder(a);
q2 = new QueueOrder(b);
q3 = new QueueOrder(c);
q4 = new QueueOrder(d);
q1.setChild(q2);
q2.setChild(q3);
q3.setChild(q4);
q4.setChild(q1);
Thread t1 = new Thread(q1);
Thread t2 = new Thread(q2);
Thread t3 = new Thread(q3);
Thread t4 = new Thread(q4);
t1.start();
t2.start();
t3.start();
t4.start();
QueueOrder q = q1;
while (!q.queue.isEmpty()) {
synchronized (q) {
if (!q.isPrinted) {
q.notify();
q.wait();
}
}
q = q.child;
}
t1.join();
t2.join();
t3.join();
t4.join();
}
}
class QueueOrder implements Runnable {
Integer[] arr;
QueueOrder child;
Queue<Integer> queue = new LinkedList<>();
boolean isPrinted = false;
QueueOrder(Integer[] arr) {
this.arr = arr;
queue.addAll(Arrays.asList(arr));
}
public QueueOrder getChild() {
return child;
}
public void setChild(QueueOrder child) {
this.child = child;
}
public void run() {
while (!this.queue.isEmpty()) {
synchronized (this) {
if (!this.isPrinted) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
System.out.print("**" + this.queue.poll());
this.isPrinted = false;
synchronized (this) {
this.notify();
}
}
}
}
package com.test.algorithms;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
public class PrintInOrder1 {
private static Integer[] a = { 1, 1, 1 };
private static Integer[] b = { 2, 2, 2 };
private static Integer[] c = { 3, 3, 3 };
private static Integer[] d = { 4, 4, 4 };
public static void main(String[] args) throws InterruptedException {
QueueOrder1 q1 = null;
QueueOrder1 q2 = null;
QueueOrder1 q3 = null;
QueueOrder1 q4 = null;
q1 = new QueueOrder1(a);
q2 = new QueueOrder1(b);
q3 = new QueueOrder1(c);
q4 = new QueueOrder1(d);
q1.setChild(q2);
q1.isPrinted = true;
q2.setChild(q3);
q3.setChild(q4);
q4.setChild(q1);
Thread t1 = new Thread(q1);
Thread t2 = new Thread(q2);
Thread t3 = new Thread(q3);
Thread t4 = new Thread(q4);
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
}
}
class QueueOrder1 implements Runnable {
Integer[] arr;
QueueOrder1 child;
Queue<Integer> queue = new LinkedList<>();
boolean isPrinted = false;
QueueOrder1(Integer[] arr) {
this.arr = arr;
queue.addAll(Arrays.asList(arr));
}
public QueueOrder1 getChild() {
return child;
}
public void setChild(QueueOrder1 child) {
this.child = child;
}
public void run() {
while (!this.queue.isEmpty()) {
synchronized (this) {
if (!this.isPrinted) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
System.out.print("**" + this.queue.poll());
this.isPrinted = false;
synchronized (this.child) {
if(!this.child.isPrinted) {
this.child.notify();
}
}
}
}
}