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他是对的,你需要同步集合,它是共享对象而不是可运行对象。