首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >2线程间通信

2线程间通信
EN

Stack Overflow用户
提问于 2012-01-22 11:26:17
回答 4查看 1.5K关注 0票数 0

我想在两个线程之间建立这样的通信:第一个线程(Sender)向第二个线程(Receiver)发送一个整数,Receiver显示这个整数的平方。下面是我的代码:Carre.java(main) :

代码语言:javascript
复制
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 :

代码语言:javascript
复制
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

公共类接收器实现Runnable {

代码语言:javascript
复制
    @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中的异常

代码语言:javascript
复制
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中的异常

代码语言:javascript
复制
at java.lang.Object.notifyAll(Native Method)

at Sender.run(Sender.java:19)

at java.lang.Thread.run(Thread.java:636)
EN

回答 4

Stack Overflow用户

发布于 2012-01-22 11:57:45

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

你可以在这里看看:使用队列的生产者/使用者线程

票数 1
EN

Stack Overflow用户

发布于 2012-01-22 11:47:52

这里的问题还不清楚,但我建议您尝试以下几种方法:

代码语言:javascript
复制
//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... }对对象进行同步。

票数 0
EN

Stack Overflow用户

发布于 2012-01-22 18:49:10

此错误是因为您只能对当前线程为wait()的对象调用synchronizedsynchronized文档对此非常清楚。

你应该这样做:

代码语言:javascript
复制
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的锁执行类似的操作,在synchronized(lock)块中调用lock.notify()

与将lock对象传递给发送方和接收方以及编写您自己的同步逻辑相比,更好的方法是使用并发队列,如SynchronousQueue

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8960704

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档