我想在2个线程之间建立通信,如下所示:
第一个线程(Sender
)向第二个线程(Receiver
)发送一个整数,Receiver
显示该整数的平方。
这是我的代码:
Carre.java(主要):
public class Carre {
static Boolean msgArrived = Boolean.FALSE ;
static int n ;
public static void main(String[] args) {
Thread sender = new Thread(new Sender()) ;
Thread receiver = new Thread(new Receiver()) ;
sender.start() ;
receiver.start() ;
}
public int getN() {
return n;
}
}
Sender.java:
import java.util.Random;
public class Sender implements Runnable {
@Override
public void run() {
while(Carre.msgArrived == Boolean.TRUE) {
try {
wait() ;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i = 0; i < 10; i ++) {
Random ran = new Random() ;
Carre.n = ran.nextInt(100) ;
Carre.msgArrived = Boolean.TRUE ;
notifyAll() ;
}
}
}
Receiver.java
公共类Receiver实现了Runnable {
@Override
public void run() {
while(Carre.msgArrived == Boolean.FALSE) {
try {
wait() ;
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Carre.n * Carre.n) ;
Carre.msgArrived = Boolean.TRUE ;
notifyAll() ;
}
}
&安培;当我尝试执行我的代码时,我收到此错误消息:
线程“Thread-1”中的异常java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at Receiver.run(Receiver.java:12)
at java.lang.Thread.run(Thread.java:636)
线程“Thread-0”中的异常java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at Sender.run(Sender.java:19)
at java.lang.Thread.run(Thread.java:636)
答案 0 :(得分:1)
在我看来,最好不要直接使用线程,因为它们是太低级别的并发实体,因此更难以使用。 您应该能够通过java.util.concurrent包工具更轻松地计算出您的生产者/消费者场景。
答案 1 :(得分:0)
目前还不清楚究竟是什么问题,但我建议尝试以下内容:
//Carre.java
public class Carre {
//package level access
static List<Integer> queue = new ArrayList<Integer>();
public static void main(String[] args) {
Thread sender = new Sender();
Thread receiver = new Receiver();
sender.start();
receiver.start();
}
//package-level access
static boolean available() {
synchronized(queue) {
return ! queue.isEmpty();
}
}
static int getNext() {
synchronized(queue) {
return queue.remove(0);
}
}
static void enqueue(int next) {
synchronized(queue) {
queue.add(next);
}
}
}
//Sender.java
public class Sender extends Thread {
private boolean stop = false;
public void stopRunning() {
stop = true;
}
@Override
public void run() {
while (! stop) {
for(int i = 0; i < 10; i ++) {
Random ran = new Random() ;
Carre.enqueue(ran.nextInt(100));
}
try {
synchronized(Carre.queue) {
Carre.queue.notify();
Carre.queue.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//Receiver.java
public class Receiver extends Thread {
private boolean stop = false;
public void stopRunning() {
stop = true;
}
@Override
public void run() {
while(! stop) {
while (Carre.available()) {
int next = Carre.getNext();
System.out.println(next * next) ;
}
try {
synchronized(Carre.queue) {
Carre.queue.notify();
Carre.queue.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
当然,由于类之间的紧密耦合,这远非理想的编码风格,但它确实展示了如何跨线程共享数据的基础知识,这使得生产者和消费者线程保持同步。
请注意,如果您收到java.lang.IllegalMonitorStateException
,那是因为您在首先未同步的对象上调用wait()
或notify()
。您可以通过执行synchronized(object) { //code... }
来对对象进行同步。
答案 2 :(得分:0)
错误是因为您只能在当前线程为wait()
的对象上调用notify()
和synchronized
。 documentation对此很清楚。
你应该这样做:
public static void main(String[] args) {
Object lock = new Object();
Thread sender = new Thread(new Sender(lock)) ;
Thread receiver = new Thread(new Receiver(lock)) ;
sender.start() ;
receiver.start() ;
}
class Sender implements Runnable {
private final Object lock;
Sender(Object lock) { this.lock = lock; }
@Override
public void run() {
synchronized (lock) {
while(Carre.msgArrived == Boolean.TRUE) {
try {
lock.wait() ;
} catch (InterruptedException ex) {
/* Interruption is a request to abort operation ASAP. */
ex.printStackTrace();
Thread.currentThread().interrupt();
return;
}
}
}
...
}
使用Receiver
的锁定执行类似操作,在lock.notify()
块内调用synchronized(lock)
。
甚至比将lock
对象传递给发送方和接收方,并编写自己的同步逻辑更好,使用并发队列,如SynchronousQueue
。
答案 3 :(得分:0)
你必须在synchronized块或方法甚至类中调用notify()wait()。请参阅java中线程的竞争条件,了解我们使用synchronized的原因。