在Java中,线程同步与互斥是非常重要的概念。以往我们使用synchronized关键字来锁定某个方法或某段代码块,以保持线程的同步与互斥。在这篇文章中,我们将介绍另一个重要的关键字——notify()。notify()方法的作用是唤醒等待线程队列中的某个线程,并将该线程移动到锁池中。对于正在运行的线程,notify()方法不会产生任何影响。如果你想在某个时刻唤醒一个等待线程,你需要在代码中仔细地实现它。
一、notify()方法的使用
我们将具体了解notify()方法的使用。notify()方法要在synchronized块中调用,以确保该对象的锁定机制。
public class NotifyTest {
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
public void run() {
synchronized(this) {
for(int i=0; i<100 ; i++) {
total += i;
}
notify();
}
}
}
在这个例子中,我们创建了两个线程:一个线程是主线程,另一个线程是ThreadB。main线程在运行时,调用synchronized方法锁定ThreadB对象。然后,main线程调用ThreadB.wait()方法来等待ThreadB线程的完成。在ThreadB线程完成之后,total的值会被打印出来。
二、notify()方法的限制
notify()方法除了唤醒等待线程之外,它并没有其他的效果。如果一个线程被notify()唤醒,它不会立即执行。相反,该线程需要重新进入该对象的锁池并等待重新获得该对象的锁,然后才能继续执行。
还有一个限制是,notify()方法只会唤醒等待队列中的其中一个线程,并且我们不能指定哪个线程会被唤醒。也就是说,我们无法控制具体唤醒哪一个等待线程。
三、notifyAll()方法的使用
我们介绍了notify()方法的基本使用和限制,现在我们将介绍另一个方法:notifyAll()。notifyAll()方法唤醒等待队列中的所有线程。
public class NotifyAllTest {
public static void main(String[] args) {
Message msg = new Message("process it");
Waiter waiter1 = new Waiter(msg);
new Thread(waiter1,"waiter1").start();
Waiter waiter2 = new Waiter(msg);
new Thread(waiter2, "waiter2").start();
Notifier notifier = new Notifier(msg);
new Thread(notifier, "notifier").start();
System.out.println("All threads started");
}
}
class Message {
private String msg;
public Message(String str){
this.msg=str;
}
public String getMsg() {
return msg;
}
public void setMsg(String str) {
this.msg=str;
}
}
class Waiter implements Runnable{
private Message msg;
public Waiter(Message m){
this.msg=m;
}
public void run() {
String name = Thread.currentThread().getName();
synchronized (msg) {
try{
System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
msg.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
//process the message now
System.out.println(name+" processed: "+msg.getMsg());
}
}
}
class Notifier implements Runnable {
private Message msg;
public Notifier(Message msg) {
this.msg = msg;
}
public void run() {
Thread.currentThread().setName("notifier");
System.out.println("Started notifying at time:"+System.currentTimeMillis());
synchronized (msg) {
msg.setMsg("Notifying all waiting threads");
msg.notifyAll();
// msg.notify();
}
}
}
在这个例子中,我们创建了一个Message类,一个Waiter类和一个Notifier类。Waiter类等待Notifier类的通知,Notifier类发出通知,等待的Waiter类会被唤醒并继续执行。
在这个例子中,我们使用了wait()和notifyAll()方法。wait()方法可将当前线程放入对象的等待队列中,并释放对象锁,以便其他线程可以获得该对象的锁并继续执行。notifyAll()方法将唤醒所有正在等待该对象的线程,这些线程将重新进入对象的锁池,并准备重新获得对象的锁。
四、总结
在本篇文章中,我们介绍了Java中notify()方法的基本使用和限制,以及notifyAll()方法的使用。notify()方法是唤醒等待队列中的某个线程,notifyAll()方法是唤醒等待队列中的所有线程。在使用notify()和notifyAll()方法时,需要确保已经获得对象锁,以便它可以执行正确的操作。
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/193898.html
微信扫一扫
支付宝扫一扫