等待和通知不仅是常规方法或同步实用程序,还不仅仅是Java中两个线程之间的通信机制。 如果无法通过任何Java关键字(例如,synchronized)使用此机制,则Object类是使它们可用于每个对象的正确位置。 请记住,同步和等待通知是两个不同的区域,不要混淆它们是相同还是相关的。 同步是为了相互排斥并确保Java类的线程安全(如竞争条件),而等待和通知是两个线程之间的通信机制。
锁是基于每个对象可用的,这是在对象类而不是线程类中声明wait和notify的另一个原因。
在Java中,为了输入代码的关键部分,线程需要锁,并且它们等待锁,他们不知道哪个线程持有锁,而是仅知道某个线程持有该锁,并且应该等待锁而不是知道哪个线程。 线程在同步块内部,并要求他们释放锁定。 这个类比适合等待并通知对象类,而不是Java中的线程。
打个比方:一个Java线程是一个用户,而厕所是该线程希望执行的代码块。 Java提供了一种方法,该方法使用synchorinized keywokd锁定当前正在执行它的线程的代码,并使其他希望使用它的线程等待第一个线程完成。 这些其他线程处于等待状态。 Java不像服务站那样公平,因为没有等待线程的队列。 无论等待线程的顺序如何,任何一个等待线程都可以接下该监视器。 唯一的保证是所有线程迟早都会使用受监视的代码。
资源
如果查看以下生产者和消费者代码:
sharedQueue对象在producer and consumer线程之间进行线程间通信。
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ProducerConsumerSolution {
public static void main(String args[]) {
Vector sharedQueue = new Vector();
int size = 4;
Thread prodThread = new Thread(new Producer(sharedQueue, size), "Producer");
Thread consThread = new Thread(new Consumer(sharedQueue, size), "Consumer");
prodThread.start();
consThread.start();
}
}
class Producer implements Runnable {
private final Vector sharedQueue;
private final int SIZE;
public Producer(Vector sharedQueue, int size) {
this.sharedQueue = sharedQueue;
this.SIZE = size;
}
@Override
public void run() {
for (int i = 0; i < 7; i++) {
System.out.println("Produced: " + i);
try {
produce(i);
} catch (InterruptedException ex) {
Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void produce(int i) throws InterruptedException {
// wait if queue is full
while (sharedQueue.size() == SIZE) {
synchronized (sharedQueue) {
System.out.println("Queue is full " + Thread.currentThread().getName() + " is waiting , size: "
+ sharedQueue.size());
sharedQueue.wait();
}
}
// producing element and notify consumers
synchronized (sharedQueue) {
sharedQueue.add(i);
sharedQueue.notifyAll();
}
}
}
class Consumer implements Runnable {
private final Vector sharedQueue;
private final int SIZE;
public Consumer(Vector sharedQueue, int size) {
this.sharedQueue = sharedQueue;
this.SIZE = size;
}
@Override
public void run() {
while (true) {
try {
System.out.println("Consumed: " + consume());
Thread.sleep(50);
} catch (InterruptedException ex) {
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private int consume() throws InterruptedException {
//wait if queue is empty
while (sharedQueue.isEmpty()) {
synchronized (sharedQueue) {
System.out.println("Queue is empty " + Thread.currentThread().getName()
+ " is waiting , size: " + sharedQueue.size());
sharedQueue.wait();
}
}
//Otherwise consume element and notify waiting producer
synchronized (sharedQueue) {
sharedQueue.notifyAll();
return (Integer) sharedQueue.remove(0);
}
}
}
资源