通信inter 2线程

时间:2012-01-22 11:26:17

标签: java multithreading

我想在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)

4 个答案:

答案 0 :(得分:1)

在我看来,最好不要直接使用线程,因为它们是太低级别的并发实体,因此更难以使用。 您应该能够通过java.util.concurrent包工具更轻松地计算出您的生产者/消费者场景。

您可以在此处查看:Producer/Consumer threads using a Queue

答案 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()synchronizeddocumentation对此很清楚。

你应该这样做:

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的原因。