Java 如何在非线程的对象上调用wait()和notify()方法?
如何在非线程的对象上调用Java 如何在非线程的对象上调用wait()和notify()方法?,java,multithreading,wait,notify,Java,Multithreading,Wait,Notify,如何在非线程的对象上调用wait()和notify()方法?这真的没有道理,是吗 当然,这是有意义的,因为这两种方法适用于所有Java对象。有人能解释一下吗?我无法理解如何使用wait()和notify()在线程之间通信。您可以使用wait()和notify()来同步逻辑。例如 synchronized (lock) { lock.wait(); // Will block until lock.notify() is called on another thread. } // So
wait()
和notify()
方法?这真的没有道理,是吗
当然,这是有意义的,因为这两种方法适用于所有Java对象。有人能解释一下吗?我无法理解如何使用wait()
和notify()
在线程之间通信。您可以使用wait()
和notify()
来同步逻辑。例如
synchronized (lock) {
lock.wait(); // Will block until lock.notify() is called on another thread.
}
// Somewhere else...
...
synchronized (lock) {
lock.notify(); // Will wake up lock.wait()
}
类成员
Object lock=new Object()代码>在Java中,所有对象都实现这两个方法,显然,如果没有监视器,那么这两个方法是无用的。此方法只能由作为此对象监视器所有者的线程调用
因此,我认为您必须确保有一个线程是对象上的监视器。锁定是关于保护共享数据的
锁位于受保护的数据结构上。线程是访问数据结构的对象。锁位于数据结构对象上,以防止线程以不安全的方式访问数据结构
任何对象都可以用作内部锁(意思是与synchronized
一起使用)。通过这种方式,您可以通过向访问共享数据的方法添加synchronized修饰符来保护对任何对象的访问
对用作锁的对象调用wait
和notify
方法。锁是一个共享通信点:
- 当具有锁的线程调用其上的
notifyAll
时,等待该锁的其他线程将收到通知。当具有锁的线程调用其上的notify
时,等待该锁的其中一个线程将收到通知
- 当有锁的线程调用
wait
时,该线程释放锁并进入休眠状态,直到a)它收到通知,或b)它只是任意唤醒(“伪唤醒”);等待的线程仍然停留在调用中等待,直到由于这两个原因之一而被唤醒,然后线程必须重新获取锁,然后才能退出wait方法
请参见,Drop类是共享数据结构,使用生产者和消费者可运行程序的线程正在访问它。锁定Drop对象控制线程访问Drop对象数据的方式
线程在JVM实现中被用作锁,建议应用程序开发人员避免使用线程作为锁。例如,报告说:
此实现使用This.wait调用的循环,该循环以This.isAlive为条件。当线程终止时,调用this.notifyAll方法。建议应用程序不要在线程实例上使用wait、notify或notifyAll
Java5引入了显式锁,实现了Java.util.concurrent.locks.Lock
。这些锁比隐式锁更灵活;有类似于等待和通知(等待和信号)的方法,但它们是基于条件的,而不是基于锁的。有多个条件可以只针对那些等待特定类型通知的线程。您可以使用staticthread
class方法sleep()
停止线程一段时间
如果要停止某些对象,需要在syncronized
块内调用此方法
public class Main {
//some code
public void waitObject(Object object) throws InterruptedException {
synchronized(object) {
object.wait();
}
}
public void notifyObject(Object object) throws InterruptedException {
synchronized(object) {
object.notify();
}
}
}
另外,如果我错误理解了您的问题(英语不是我的母语)当您在同步块中放置一些代码时,我很抱歉:
sychronized(lock){...}
想要执行此块中的任何内容的线程首先会获得对象上的锁,并且一次只有一个线程可以执行锁定在同一对象上的代码。任何对象都可以用作锁,但在选择与作用域相关的对象时应小心。例如,当您有多个线程向帐户添加某些内容时,它们都有一些代码在块中负责,如:
sychronized(this){...}
然后不会发生同步,因为它们都锁定在不同的对象上。相反,您应该使用account对象作为锁。
现在考虑这些线程也有从帐户中退出的方法。在这种情况下,可能会出现一种情况,即希望提取某物的线程遇到一个空帐户。它应该等到有了钱,然后释放对其他线程的锁,以避免死锁。这就是wait和notify方法的用途。在本例中,遇到空帐户的线程将释放锁,并等待来自进行存款的某个线程的信号:
while(balance < amountToWithdraw){
lock.wait();
}
正如您所看到的,方法wait和notify仅在同步块或方法中有意义
Wait和notify不仅仅是普通的方法或同步工具,更重要的是它们是Java中两个线程之间的通信机制。如果这个机制不能通过任何java关键字(如synchronized)使用,那么对象类就是使它们对每个对象都可用的正确位置。记住,synchronized和wait notify是两个不同的区域,不要混淆它们是相同的或相关的。Synchronized是在两个线程之间的通信机制wait和notify的同时,提供互斥性,保证Java类的线程安全性,比如争用条件
锁在每个对象的基础上可用,这是在对象类而不是线程类中声明wait和notify的另一个原因
在Java中,为了进入代码的关键部分,线程需要锁并等待锁,它们不知道哪个线程持有锁,而只是知道锁被某个线程持有,它们应该等待锁,而不是知道哪个线程在同步块中并要求它们释放锁。这个类比适用于等待和通知处于o状态
while(balance < amountToWithdraw){
lock.wait();
}
balance += amountToDeposit;
lock.signallAll;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ProducerConsumerSolution {
public static void main(String args[]) {
Vector<Integer> sharedQueue = new Vector<Integer>();
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<Integer> sharedQueue;
private final int SIZE;
public Producer(Vector<Integer> 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<Integer> sharedQueue;
private final int SIZE;
public Consumer(Vector<Integer> 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);
}
}
}