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 为什么消费者线程不能从Vector中删除消息?_Java_Multithreading_Producer Consumer - Fatal编程技术网

Java 为什么消费者线程不能从Vector中删除消息?

Java 为什么消费者线程不能从Vector中删除消息?,java,multithreading,producer-consumer,Java,Multithreading,Producer Consumer,我试图为生产者/消费者问题创建一个解决方案,其中一个线程将消息放入向量中,另一个线程将消息从向量中移除 import java.util.Vector; public class Producer implements Runnable { static final int MAXQUEUE = 5; private Vector<String> messages; public Producer(Vector<String> messages)

我试图为生产者/消费者问题创建一个解决方案,其中一个线程将消息放入向量中,另一个线程将消息从向量中移除

import java.util.Vector;
public class Producer implements Runnable {
    static final int MAXQUEUE = 5;
    private Vector<String> messages;

    public Producer(Vector<String> messages) {
        super();
        this.messages = messages;
    }

    @Override
    public void run() {
        try {
            while (true) 
                putMessage();
        } catch (InterruptedException e) {
        }
    }

    private synchronized void putMessage() throws InterruptedException {
        while (messages.size() == MAXQUEUE) {
            wait();
        }
        messages.addElement(new java.util.Date().toString());
        System.out.println("put message");
        notifyAll();
    }

    public static void main(String args[]) {    
        Vector<String> messages = new Vector<String>();
        new Thread(new Producer(messages)).start();
        new Thread(new Consumer(messages)).start();
    }
}

class Consumer implements Runnable{
    public Consumer(Vector<String> messages) {
        super();
        this.messages = messages;
    }
    private Vector<String> messages;

    public synchronized String getMessage() throws InterruptedException {
        notifyAll();
        while (messages.size() == 0) {
            wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
        }
        String message = (String) messages.firstElement();
        messages.removeElement(message);
        return message;
    }

    @Override
    public void run() {
        try {
            while (true) {
                String message = getMessage();
                System.out.println("Got message: " + message);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
import java.util.Vector;
公共类生产者实现Runnable{
静态最终int MAXQUEUE=5;
专用向量消息;
公共制作人(矢量信息){
超级();
this.messages=消息;
}
@凌驾
公开募捐{
试一试{
while(true)
putMessage();
}捕捉(中断异常e){
}
}
private synchronized void putMessage()引发InterruptedException{
while(messages.size()==MAXQUEUE){
等待();
}
messages.addElement(新java.util.Date().toString());
System.out.println(“put消息”);
notifyAll();
}
公共静态void main(字符串args[]){
向量消息=新向量();
新线程(新生产者(消息)).start();
新线程(新使用者(消息)).start();
}
}
类使用者实现Runnable{
公共消费者(矢量信息){
超级();
this.messages=消息;
}
专用向量消息;
公共同步字符串getMessage()引发InterruptedException{
notifyAll();
while(messages.size()==0){
wait();//通过从同步块执行wait(),线程放弃对锁的控制,进入睡眠状态。
}
String message=(String)messages.firstElement();
messages.removelement(消息);
返回消息;
}
@凌驾
公开募捐{
试一试{
while(true){
String message=getMessage();
System.out.println(“得到消息:+消息”);
}
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}

每当我运行程序时,它都会打印put消息5次。即使在notifyAll()之后,我也不明白,它并没有给使用者提供锁。

登录到控制台的速度非常慢,因此,如果不持有锁就这样做,则会给使用者一个机会

@Override
public void run() {
    try {
        while (true) {
            // slows the producer a little to give the consumer a chance to get the lock.
            System.out.println("put message");
            putMessage();
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private void putMessage() throws InterruptedException {
    synchronized  (messages) {
        while (messages.size() == MAXQUEUE) {
            messages.wait();
        }
        messages.addElement(new java.util.Date().toString());
        messages.notifyAll();
    }
}
顺便说一句,你可以写这个

public String getMessage() throws InterruptedException {
    synchronized (messages) {
        while (messages.isEmpty()) {
            messages.wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
        }
        messages.notifyAll();
        return messages.remove(0);
    }
}

您的代码不工作,因为您的两个线程没有在同一个监视器上通知/等待

它们各自在自己的监视器上通知和等待,而不是共享监视器。更改代码以使用共享监视器,例如
消息
,包括同步

private void putMessage() throws InterruptedException {
    synchronized (messages) { // <======
        while (messages.size() == MAXQUEUE) {
            messages.wait();  // <======
        }
        messages.addElement(new java.util.Date().toString());
        System.out.println("put message");
        messages.notifyAll(); // <======
    }
}

public String getMessage() throws InterruptedException {
    synchronized (messages) { // <======
        while (messages.size() == 0) {
            messages.wait();  // <======
        }
        String message = (String) messages.firstElement();
        messages.removeElement(message);
        messages.notifyAll(); // <======
        return message;
    }
}
private void putMessage()引发InterruptedException{

synchronized(messages){//这可能不是问题所在,但请尝试将main方法放入另一个驱动程序类中?您正在尽可能快地放入,直到它已满,如果使用者在生产者调用wait()之前无法获得锁,我不会感到惊讶.BTW使用BlockingQueue将更简单、更高效,因为生产者不会锁定消费者。即,您可以同时添加和删除。另请注意:随着添加更多元素,删除第一个元素的成本会更高,并且使用1998年替换的向量与使用LinkedList或Q等集合相比不会增加任何价值ueue@Peter我能做什么小小的改变才能让它工作?我不能使用任何并发api数据结构。我们不能用同步方法而不是同步块吗?@Vicky不,因为同步方法与
Synchronized(此)相同{
,这意味着这两个类正在两个不同的对象上同步。谢谢Andreas。我现在明白了问题所在。在本例中,“this”是Thread对象,对吗?@Vicky
这是
生产者
消费者
,而不是
线程
@Vicky他是对的,你需要同步集合,它是共享对象而不是可运行对象。