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方法