我是JAVA的新手,在JAVA学习多线程。这是我的代码段。
import java.util.*;
import java.lang.*;
import java.io.*;
class Manager {
static final int MAXQUEUE = 5;
private Vector messages = new Vector();
public synchronized void putMessage() throws InterruptedException {
while (messages.size() == MAXQUEUE) {
System.out.println("waiting for space in queue ");
wait();
}
messages.addElement(new java.util.Date().toString());
System.out.println("created a new message and message count is " + messages.size());
notify();
}
public synchronized String getMessage() throws InterruptedException {
notify();
while (messages.size() == 0) {
System.out.println("queue is empty ");
wait();
}
String message = (String) messages.firstElement();
messages.removeElement(message);
System.out.println("removed a message and message count is " + messages.size());
return message;
}
}
class Producer extends Thread {
Manager myRef;
Producer(Manager ref) {
myRef = ref;
}
public void run() {
try {
while (true) {
myRef.putMessage();
sleep(1000);
}
} catch (InterruptedException e) {
}
}
}
class Consumer extends Thread {
Manager myRef;
Consumer(Manager ref) {
myRef = ref;
}
public void run() {
try {
while (true) {
String message = myRef.getMessage();
System.out.println("Got message: " + message);
sleep(2000);
}
} catch (InterruptedException e) {
}
}
public static void main(String args[]) {
Manager ref = new Manager();
Producer producer = new Producer(ref);
producer.start();
new Consumer(ref).start();
}
}
我的期待:
但是,发生了什么:
created a new message and message count is 1
removed a message and message count is 0
Got message: Thu Aug 13 07:26:45 GMT 2015
created a new message and message count is 1
removed a message and message count is 0
Got message: Thu Aug 13 07:26:46 GMT 2015
and so on.....
正如您所看到的,我的消费者线程能够调用readMessage(),即使manager对象的锁定与执行putMessage()的Producer线程有关。如果一个线程正在执行实例方法,其他线程如何能够调用另一个实例方法?
请纠正我的理解。
答案 0 :(得分:2)
首先,您的生产者Thread执行putMessage
方法。他创建了一个项目并将其添加到messages
列表中。当putMessage
完成并创建了一个项目时,生产者线程将进入休眠状态。
当消费者线程醒来时,他可以自由访问getMessage
方法并使用唯一的项目。然后消费者进入睡眠状态。
此过程始终重复。正如您所期望的那样,synchronized关键字可以防止一个对象的任何同步方法可以并行执行。正如我解释的那样,并没有发生。线程只是在访问方法时交替使用。每个方法调用只生成或消耗一个项目。
答案 1 :(得分:2)
这是java多线程的正确行为。
首先,我的Producer线程将控制Manager上的锁定 宾语。它将调用putMessage()直到count为5并且将会 释放锁。
我不确定您是否为此行编写了代码
It will call putMessage() until the count is 5 and will release the lock.
因为您的代码显示
public synchronized void putMessage() throws InterruptedException {
// Check if messages list size is full. If full then wait for emptying
while (messages.size() == MAXQUEUE) {
System.out.println("waiting for space in queue ");
wait();
}
// If not, add one element. Where have you written code for adding 5 elements at once.
messages.addElement(new java.util.Date().toString());
System.out.println("created a new message and message count is " + messages.size());
notify();
}
请查看以下链接。
答案 2 :(得分:1)
逐步执行每个线程:
生产者线程开始:
调用run()方法调用putMessage方法
putMessage():它是同步的,因此作为生产者线程的当前线程获取当前Manager对象的锁定。现在,在此期间,没有其他线程可以在同一对象上调用另一个同步方法。由于消息的大小是< MAXQUEUE(5),因为它只是第一次插入,它继续将一个元素插入到矢量消息中。然后它调用notify()来指示任何其他等待线程准备好重新获得锁。重要的是要注意,调用notify()本身不会释放锁。如果您愿意,可以在调用notify()之后继续执行操作。 Notify()只是等待线程准备好排队获取锁的信号。仅当同步函数退出或调用wait()时才会释放锁。
线程休眠1秒钟。
消费者线程开始:
调用run()方法调用getMessage()
getMessage():如上所述,它将以类似的原理工作,如果它不为空,则从向量中提取消息。请注意,它在进入时首先调用notify()。这样做是为了通知任何等待的生产者线程准备就绪,因为在getMessage执行之后它保证了向量的大小将小于MAXSIZE。再次如前所述,简单地调用notify()不会释放锁。
线程睡2秒钟。
这两个线程以并行方式执行,当你让使用者睡眠时间是生产者的两倍时,你会注意到缓冲区将在某个时候被填充,然后,当我们实际需要wait和notify方法时