Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 通知不同对象中的线程_Java_Multithreading_Wait_Producer Consumer_Notify - Fatal编程技术网

Java 通知不同对象中的线程

Java 通知不同对象中的线程,java,multithreading,wait,producer-consumer,notify,Java,Multithreading,Wait,Producer Consumer,Notify,如何在下面的程序中通知线程从一个对象到另一个对象,而不在下面的生产者和消费者问题中使用同步方法 我正在为put和get方法使用queue类,并在Producer类和Consumer类的run()方法中使用wait()和notify() 我的目标是在Producer类和Consumer类中使用wait()和notify()方法,而不是在Queue类中使用它们 它给出了一个非法监视器状态异常 The producer 1 put 0 Exception in thread "Producer"

如何在下面的程序中通知线程从一个对象到另一个对象,而不在下面的生产者和消费者问题中使用同步方法

我正在为
put
get
方法使用
queue
类,并在
Producer
类和
Consumer
类的
run()
方法中使用
wait()
notify()

我的目标是在
Producer
类和
Consumer
类中使用
wait()
notify()
方法,而不是在
Queue
类中使用它们

它给出了一个
非法监视器状态异常

 The producer 1 put 0 Exception in thread "Producer" 
 java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at threads.producerandconsumer$Producer.run(producerandconsumer.java:48)
at java.lang.Thread.run(Unknown Source)

Exception in thread "Consumer" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at threads.producerandconsumer$Consumer.run(producerandconsumer.java:76)
at java.lang.Thread.run(Unknown Source)
节目:

package threads;

class Queue{
    int num;

    int get(int number)
    {

        System.out.println("The Consumer "+number+" got "+num);
        return num;
    }

    void put(int n,int number)
    {

        this.num=n;
        System.out.println("The producer "+number+" put "+this.num);

    }
}

public class producerandconsumer{
    boolean flag=false;
class Producer implements Runnable{
    Queue q;
    int number;
    Producer(Queue q,int number)
    {
        this.q=q;
        this.number = number;
        new Thread(this,"Producer").start();
    }

    public void run()
    {
        for(int i=0;i<10;i++)
        {
            while(flag)
                try{
                    wait();
                }
                catch(InterruptedException e){
                    System.out.println("InterruptedException caught ");
                }
            q.put(i,number);
            flag=true;
            notify();
        }
    }

}

class Consumer implements Runnable{
    Queue q;
    int number;
    Consumer(Queue q,int number)
    {
        this.q=q;
        this.number=number;
        new Thread(this,"Consumer").start();
    }

    public void run()
    {
        for(int i=0;i<10;i++)
        {
            while(!flag)
                try{
                    wait();
                    }
                    catch(InterruptedException e){
                        System.out.println("InterruptedException caught ");
                    }
                flag=false;
                notify();
                q.get(number);
        }
    }
}



public static void main(String[] args) {
    // TODO Auto-generated method stub
    producerandconsumer pc= new producerandconsumer();
    Queue q=new Queue();
    pc.new Producer(q,1);
    pc.new Consumer(q,1);


}

}

方法
wait
notify
必须在
synchronized
块内调用。这就是为什么您会得到IllegeMonitorStateException。

方法
wait
notify
必须在
synchronized
块内调用。这就是为什么会出现illegelMonitorStateException。

线程之间共享的状态是您的
队列
类,因此您必须通过使用适当的同步使其具有线程安全性。将同步代码放在
生产者
消费者
中不是一个好主意,因为这需要他们之间的额外通信,并且不能扩展

下面是一个简单的同步整数队列示例,它只能容纳一个
int
(类似于您的
队列
)。当对空队列调用
take
时,以及对已满队列调用
put
时,它会阻塞

请注意,您更应该使用现有的同步数据结构,如
BlockingQueue
的实现,用于实际应用程序

使用此队列,您可以拥有任意数量的生产者和消费者,这些生产者和消费者不需要任何进一步的同步:

static final IntQueue queue = new IntQueue();
static final int POISON_PILL = -1; // stops Consumer

class Producer implements Runnable {
    public void run() {
        try {
            for(int i = 0; i < 100; i++) {
                System.out.println("producing " + i);
                queue.put(i);
            }
        } catch (InterruptedException ex) { /* done */ }
    }
}

class Consumer implements Runnable {
    public void run() {
        try {
            int n = queue.take();
            // poison pill causes Consumer to stop
            while (n != POISON_PILL) {
                System.out.println("consuming " + i);
                n = queue.take();
            }
        } catch (InterruptedException ex) { /* done */ }
    }
}

public static void main() throws Exception {
    // create threads
    Thread p1 = new Thread(new Producer());
    Thread p2 = new Thread(new Producer());
    Thread c = new Thread(new Consumer());

    // start threads
    p1.start();
    p2.start();
    c.start();

    // wait for producers to complete
    p1.join();
    p2.join();

    // queue poison pill to stop consumer
    queue.put(POISON_PILL);

    // wait for consumer to complete
    c.join();
}
static final IntQueue queue=new IntQueue();
静态最终整型毒药丸=-1;//阻止消费者
类生成器实现了Runnable{
公开募捐{
试一试{
对于(int i=0;i<100;i++){
系统输出打印项次(“生成”+i);
排队。付诸表决(i);
}
}catch(InterruptedException ex){/*完成*/}
}
}
类使用者实现Runnable{
公开募捐{
试一试{
int n=queue.take();
//毒丸使消费者停止服用
while(n!=毒丸){
系统输出打印项次(“消耗”+i);
n=queue.take();
}
}catch(InterruptedException ex){/*完成*/}
}
}
public static void main()引发异常{
//创建线程
线程p1=新线程(新生产者());
线程p2=新线程(新生产者());
线程c=新线程(新使用者());
//开始线程
p1.开始();
p2.start();
c、 start();
//等待制作人完成
p1.连接();
p2.连接();
//排队购买毒丸以阻止消费者
队列。放置(毒药丸);
//等待消费者完成
c、 join();
}

线程之间共享的状态是您的
队列
类,因此您必须使用适当的同步使其成为线程安全的。将同步代码放在
生产者
消费者
中不是一个好主意,因为这需要他们之间的额外通信,并且不能扩展

下面是一个简单的同步整数队列示例,它只能容纳一个
int
(类似于您的
队列
)。当对空队列调用
take
时,以及对已满队列调用
put
时,它会阻塞

请注意,您更应该使用现有的同步数据结构,如
BlockingQueue
的实现,用于实际应用程序

使用此队列,您可以拥有任意数量的生产者和消费者,这些生产者和消费者不需要任何进一步的同步:

static final IntQueue queue = new IntQueue();
static final int POISON_PILL = -1; // stops Consumer

class Producer implements Runnable {
    public void run() {
        try {
            for(int i = 0; i < 100; i++) {
                System.out.println("producing " + i);
                queue.put(i);
            }
        } catch (InterruptedException ex) { /* done */ }
    }
}

class Consumer implements Runnable {
    public void run() {
        try {
            int n = queue.take();
            // poison pill causes Consumer to stop
            while (n != POISON_PILL) {
                System.out.println("consuming " + i);
                n = queue.take();
            }
        } catch (InterruptedException ex) { /* done */ }
    }
}

public static void main() throws Exception {
    // create threads
    Thread p1 = new Thread(new Producer());
    Thread p2 = new Thread(new Producer());
    Thread c = new Thread(new Consumer());

    // start threads
    p1.start();
    p2.start();
    c.start();

    // wait for producers to complete
    p1.join();
    p2.join();

    // queue poison pill to stop consumer
    queue.put(POISON_PILL);

    // wait for consumer to complete
    c.join();
}
static final IntQueue queue=new IntQueue();
静态最终整型毒药丸=-1;//阻止消费者
类生成器实现了Runnable{
公开募捐{
试一试{
对于(int i=0;i<100;i++){
系统输出打印项次(“生成”+i);
排队。付诸表决(i);
}
}catch(InterruptedException ex){/*完成*/}
}
}
类使用者实现Runnable{
公开募捐{
试一试{
int n=queue.take();
//毒丸使消费者停止服用
while(n!=毒丸){
系统输出打印项次(“消耗”+i);
n=queue.take();
}
}catch(InterruptedException ex){/*完成*/}
}
}
public static void main()引发异常{
//创建线程
线程p1=新线程(新生产者());
线程p2=新线程(新生产者());
线程c=新线程(新使用者());
//开始线程
p1.开始();
p2.start();
c、 start();
//等待制作人完成
p1.连接();
p2.连接();
//排队购买毒丸以阻止消费者
队列。放置(毒药丸);
//等待消费者完成
c、 join();
}

oh..好的..谢谢:)我可以同步run方法吗..我已删除异常。我可以显式地通知线程吗?要保持对象的监视器,需要在此对象上同步块。Synchronized方法的想法是错误的。我需要在实现Runnable的类中使用wait和notify方法,那么我该怎么做呢?我真的不明白使用wait/notify方法的原因。如果您只想同步队列访问,请使用带有队列对象的同步块。哦..好..谢谢:)我可以同步运行方法吗..?我已删除异常。我可以显式地通知线程吗?要保持对象的监视器,需要在此对象上同步块。同步方法是错误的。我需要在类中使用wait和notify方法