JAVA线程同步中wait()和notify()简洁例子

合集下载

thread wait用法

thread wait用法

thread wait用法Thread.Wait是一个线程同步的方法,它可用于暂停当前线程的执行,直到另一个线程完成其任务。

使用的一般步骤如下:1. 创建一个Thread对象,并指定一个方法或代码块作为线程执行的任务。

2. 启动线程,使其开始执行任务。

3. 在另一个线程中,使用Thread.Wait方法来使当前线程等待,直到目标线程完成任务。

4. 目标线程完成任务后,通过调用Thread.Notify或Thread.NotifyAll方法来唤醒等待的线程。

例如,假设有两个线程,一个用于打印奇数,另一个用于打印偶数。

我们希望这两个线程交替执行,并且其中一个线程必须等待另一个线程完成后才能执行。

```javaclass PrintNumbers {private boolean isOddPrinted = false;public synchronized void printOdd() {while (isOddPrinted) {try {wait(); // 等待另一个线程打印偶数} catch (InterruptedException e) {e.printStackTrace();}}// 打印奇数System.out.println("Odd: " + Thread.currentThread().getId()); isOddPrinted = true;// 唤醒等待的线程notifyAll();}public synchronized void printEven() {while (!isOddPrinted) {try {wait(); // 等待另一个线程打印奇数} catch (InterruptedException e) {e.printStackTrace();}}// 打印偶数System.out.println("Even: " + Thread.currentThread().getId()); isOddPrinted = false;// 唤醒等待的线程notifyAll();}}public class Main {public static void main(String[] args) {PrintNumbers numbers = new PrintNumbers();Thread thread1 = new Thread(() -> {for (int i = 1; i <= 10; i += 2) {numbers.printOdd();}});Thread thread2 = new Thread(() -> {for (int i = 2; i <= 10; i += 2) {numbers.printEven();}});thread1.start();thread2.start();}}```在上面的示例中,通过使用wait和notifyAll方法,我们实现了两个线程交替打印奇数和偶数的功能。

java中的wait()和notify()使用实例

java中的wait()和notify()使用实例
+ " sleep zzz...] ");
try {
synchronizeVariable.wait();
} catch (InterruptedException error) {
public static void main(String args[]) {
Thread[] threads = new Thread[2];
for (int count = 0; count < threads.length; count++) {
再往下看之前呢,首先最好复习一下Think in Java的14.3.1中第3部分内容:等待和通知,也就是wait()和notify了.
按照Think in Java中的解释:"wait()允许我们将线程置入“睡眠”状态,同时又“积极”地等待条件发生改变.而且只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒,并检查条件是否有变."
}
public static void main(String[] args) {
DemoThread demoThread1 = new DemoThread();
}
public void run(){
TestThread t = (TestThread) Thread.currentThread();
如何利用wait() notify() notifyAll()?
在synchronized代码被执行期间,线程可以调用对象的wait()方法,释放对象锁标志,进入等待状态,并且可以调用notify()或者
notifyAll()方法通知正在等待的其他线程。notify()通知等待队列中的第一个线程,notifyAll()通知的是等待队列中的所有线程。

Java多线程的同步方式和锁机制

Java多线程的同步方式和锁机制

Java多线程的同步⽅式和锁机制Object.wait(miliSec)/notify()/notifyAll()线程调⽤wait()之后可以由notify()唤醒,如果指定了miliSec的话也可超时后⾃动唤醒。

wait⽅法的调⽤会让当前线程放弃已经获取的object锁标志位,⽐如在同步代码块synchronized中调⽤wait(),则表⽰当前线程被唤醒之后需要重新获取同步代码块的锁。

另外wait/notify由于要操作对象的锁标志位,因此必须在synchronized代码块中调⽤,否则会抛出运⾏时异常IllegalMonitorStateException。

wait/notify机制出现之前,⽣产/消费实现模型的同步⼀般通过while(true)轮询实现,弊端是极⼤耗⽤CPU资源做⽆⽤的轮询。

在调⽤wait⽅法之前,线程需要获取当前实例对象的锁,执⾏wait⽅法返回之后,线程释放掉对象锁并进⼊block状态;其他线程在调⽤notify⽅法之前,也需要获取当前实例对象的锁,执⾏notify⽅法时,如果有多个线程处理block状态则从中按某规则选择⼀个唤醒,notify⽅法调⽤之后不会⽴即释放锁,要等线程的同步⽅法执⾏完毕之后才释放对象锁,因此⼀次notify调⽤只会唤醒⼀个线程,其他block的线程依旧处理block状态。

1public class App1 extends Thread {2private Object lock;3public App1(Object lock) {4super();5this.lock = lock;6 }7 @Override8public void run() {9try {10synchronized (lock) {11 System.out.println(Thread.currentThread().getName()12 + " : start to wait.");13 lock.wait();14 System.out.println(Thread.currentThread().getName()15 + " : wait ends, execute again.");16 }17 } catch (Exception e) {}18 }19 }20public class App2 extends Thread {21private Object lock;22public App2(Object lock) {23super();24this.lock = lock;25 }26 @Override27public void run() {28synchronized (lock) {29 System.out.println(Thread.currentThread().getName()30 + " : Start notify.");31 lock.notify();32 System.out.println(Thread.currentThread().getName()33 + " : notify ends, start to execute again.");34 }35 }36public static void main(String[] args) {37try {38 Object lock = new Object();39 App1 app1 = new App1(lock);40 app1.start();41 Thread.sleep(5000);42 App2 app2 = new App2(lock);43 app2.start();44 } catch (Exception e) {}45 }46 }47Thread.sleep(miliSec)线程释放CPU使⽤权,并进⼊休眠状态⼀段时间miliSec,不会放弃线程的锁标志位,⽐如如果在同步代码块synchronized中调⽤sleep(),表⽰线程将⼀直持有当前同步代码块的锁,其他线程将⼀直等待。

wait,notify等线程知识

wait,notify等线程知识

多线程之间需要协调工作。

例如,浏览器的一个显示图片的线程displayThread 想要执行显示图片的任务,必须等待下载线程 downloadThread将该图片下载完毕。

如果图片还没有下载完,displayThread可以暂停,当downloadThread完成了任务后,再通知displayThread“图片准备完毕,可以显示了”,这时,displayThread继续执行。

以上逻辑简单的说就是:如果条件不满足,则等待。

当条件满足时,等待该条件的线程将被唤醒。

在Java中,这个机制的实现依赖于wait/notify。

等待机制与锁机制是密切关联的。

例如:线程A:synchronized(obj) {while(!condition) {obj.wait();}obj.doSomething();}当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。

在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:线程B:synchronized(obj) {condition = true;obj.notify();}需要注意的概念是:1、调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在 synchronized(obj) {...}代码段内。

即:obj.wait(), obj.notify()必须在synchronized(obj){}内部,也就是说,必须得先得到锁才可以wait, nofity2、主调obj.wait()的线程(线程A),在obj.wait()执行时,释放掉锁3、线程A再次运行时,必须要得到锁,而且,这次运行是从obj.wait()后的第一条语句开始的(当然不包括obj.wait())4、如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。

Java wait(),notify(),notifyall()

Java wait(),notify(),notifyall()

最简实例说明wait、notify、notifyAll的使用方法博客分类:∙java 基础多线程JVMthreadIDEA/*** 转载请注明作者longdick **/wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。

这三个方法最终调用的都是jvm级的native方法。

随着jvm运行平台的不同可能有些许差异。

∙如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。

∙如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。

∙如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。

其中wait方法有三个over load方法:wait()wait(long)wait(long,int)wait方法通过参数可以指定等待的时长。

如果没有指定参数,默认一直等待直到被通知。

以下是一个演示代码,以最简洁的方式说明复杂的问题:简要说明下:NotifyThread是用来模拟3秒钟后通知其他等待状态的线程的线程类;WaitThread是用来模拟等待的线程类;等待的中间对象是flag,一个String对象;main方法中同时启动一个Notify线程和三个wait线程;Java代码1.public class NotifyTest {2. private String flag = "true";3.4. class NotifyThread extends Thread{5. public NotifyThread(String name) {6. super(name);7. }8. public void run() {9. try {10. sleep(3000);//推迟3秒钟通知11. } catch (InterruptedException e) {12. e.printStackTrace();13. }14.15. flag = "false";16. flag.notify();17. }18. };19.20. class WaitThread extends Thread {21. public WaitThread(String name) {22. super(name);23. }24.25. public void run() {26.27. while (flag!="false") {28. System.out.println(getName() + " begin waiting!");29. long waitTime = System.currentTimeMillis();30. try {31. flag.wait();32. } catch (InterruptedException e) {33. e.printStackTrace();34. }35. waitTime = System.currentTimeMillis() - waitTime;36. System.out.println("wait time :"+waitTime);37. }38. System.out.println(getName() + " end waiting!");39.40. }41. }42.43. public static void main(String[] args) throws InterruptedException {44. System.out.println("Main Thread Run!");45. NotifyTest test = new NotifyTest();46. NotifyThread notifyThread =test.new NotifyThread("notify01");47. WaitThread waitThread01 = test.new WaitThread("waiter01");48. WaitThread waitThread02 = test.new WaitThread("waiter02");49. WaitThread waitThread03 = test.new WaitThread("waiter03");50. notifyThread.start();51. waitThread01.start();52. waitThread02.start();53. waitThread03.start();54. }55.56.}OK,如果你拿这段程序去运行下的话,会发现根本运行不了,what happened?满屏的ng.IllegalMonitorStateException。

notify和wait用法

notify和wait用法

notify和wait用法在编程中,notify和wait是用于在多线程中实现线程间通信的重要方法。

它们是Java中Object类中的两个同步方法,用于协调线程的执行顺序和共享资源的访问。

本文将详细介绍notify和wait的用法,并比较它们的区别和注意事项。

1. notify用法:notify(方法用于唤醒在此对象监视器上等待的单个线程。

如果有多个线程在等待,它们中的任意一个被唤醒,具体哪一个线程被唤醒是随机的。

notify(方法必须在同步块或同步方法中调用,否则会抛出IllegalMonitorStateException异常。

示例代码如下:```javapublic class MyThread implements Runnableprivate final Object lock;public MyThread(Object lock)this.lock = lock;}public void rusynchronized (lock)trySystem.out.println("Thread " +Thread.currentThread(.getId( + " is waiting");lock.wait(; // 线程等待,释放锁System.out.println("Thread " +Thread.currentThread(.getId( + " is notified");} catch (InterruptedException e)e.printStackTrace(;}}}public static void main(String[] args) throws InterruptedExceptionObject lock = new Object(;Thread thread1 = new Thread(new MyThread(lock));Thread thread2 = new Thread(new MyThread(lock));thread1.start(;thread2.start(;Thread.sleep(1000); // 确保线程1和2都处于等待状态synchronized (lock)lock.notify(; // 随机唤醒一个线程}thread1.join(;thread2.join(;}```以上代码新建了两个线程,它们在同一个对象锁lock上等待,并通过lock.wait(方法释放锁。

Java的wait(),notify()和notifyAll()使用心得

Java的wait(),notify()和notifyAll()使用心得

Java的wait(),notify()和notifyAll()使⽤⼼得wait(),notify()和notifyAll()都是ng.Object的⽅法:wait(): Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.notify(): Wakes up a single thread that is waiting on this object's monitor.notifyAll(): Wakes up all threads that are waiting on this object's monitor.这三个⽅法,都是Java语⾔提供的实现线程间阻塞(Blocking)和控制进程内调度(inter-process communication)的底层机制。

在解释如何使⽤前,先说明⼀下两点:1. 正如Java内任何对象都能成为锁(Lock)⼀样,任何对象也都能成为条件队列(Condition queue)。

⽽这个对象⾥的wait(), notify()和notifyAll()则是这个条件队列的固有(intrinsic)的⽅法。

2. ⼀个对象的固有锁和它的固有条件队列是相关的,为了调⽤对象X内条件队列的⽅法,你必须获得对象X的锁。

这是因为等待状态条件的机制和保证状态连续性的机制是紧密的结合在⼀起的。

(An object's intrinsic lock and its intrinsic condition queue are related: in order to call any of the condition queue methods on object X, you must hold the lock on X. This is because the mechanism for waiting for state-based conditions is necessarily tightly bound to the mechanism fo preserving state consistency)根据上述两点,在调⽤wait(), notify()或notifyAll()的时候,必须先获得锁,且状态变量须由该锁保护,⽽固有锁对象与固有条件队列对象⼜是同⼀个对象。

为什么wait和notify必须在同步方法或同步块中调用

为什么wait和notify必须在同步方法或同步块中调用

为什么wait和notify必须在同步方法或同步块中调用在理解为什么wait(和notify(必须在同步方法或同步块中调用之前,我们需要先了解两者的作用以及与线程的关系。

wait(方法是Object类的一个方法,它使当前线程进入等待状态,直到其他线程调用相同对象的notify(或notifyAll(方法唤醒它。

notify(方法是Object类的一个方法,它唤醒一个等待在该对象上的线程。

Java中的线程是并发执行的,每个线程有一个自己的执行顺序。

然而,在多线程的环境中,存在着线程之间的资源竞争,多个线程可能会同时访问或修改共享的数据。

为了保证数据的一致性和避免竞争条件,Java提供了synchronized关键字和相关的wait(和notify(方法。

synchronized关键字用来创建一个互斥区域,只有一个线程可以进入该区域执行代码,其他线程必须等待。

当一个线程调用一些对象的synchronized方法或synchronized块时,它必须先获得该对象的锁。

如果对象的锁已经被其他线程获得,那么调用线程将被阻塞,直到锁被释放。

wait(和notify(方法是与synchronized关键字搭配使用的,用于实现线程间的协作与通信。

当线程调用wait(方法时,它会释放当前持有的对象锁,并进入等待状态。

其他线程调用相同对象的notify(或notifyAll(方法时,会唤醒一个等待在该对象上的线程,被唤醒的线程将重新竞争获取该对象的锁,并从wait(方法返回继续执行。

首先,wait(和notify(方法都要求调用线程必须是所属对象的锁的持有者。

因为只有锁的持有者才能释放锁并进入等待状态,同时也只有锁的持有者才能唤醒其他等待的线程。

这样可以防止多个线程同时对对象进行操作而导致的数据不一致问题。

其次,wait(和notify(方法必须在同步方法或同步块中调用,是因为这样才能确保调用线程在调用wait(和notify(方法时已经获得了对象的锁。

java的wait方法

java的wait方法

在Java 中,wait()方法是Object类的一个实例方法,用于将当前线程置于等待状态,直到其他线程调用相同对象上的notify()或notifyAll()方法唤醒它。

这一机制通常用于多线程之间的协调和同步。

wait()方法的基本语法如下:synchronized (obj) {while (condition) {obj.wait();}// 执行等待后的操作}其中,obj 是对象的引用,condition 是一个布尔表达式,用于检查线程是否应该等待。

在使用wait() 方法时,通常与synchronized 关键字一起使用,以确保线程在等待时不会被其他线程打断。

下面是wait() 方法的主要特征和用法:1. 线程等待:调用wait() 方法的线程将进入等待状态,直到其他线程调用相同对象上的notify() 或notifyAll() 方法来唤醒它。

2. 释放锁:在调用wait() 时,线程会释放它持有的锁,允许其他线程进入同步块。

一旦线程被唤醒,它将重新尝试获取锁。

3. 条件等待:wait() 方法通常与一个条件表达式结合使用,以便在满足特定条件之前一直等待。

在等待过程中,可以通过其他线程改变条件来唤醒等待线程。

以下是一个简单的例子,演示了如何使用wait() 和notify() 来实现线程之间的协作:public class WaitNotifyExample {public static void main(String[] args) {final Object lock = new Object();Thread waitingThread = new Thread(() -> {synchronized (lock) {try {System.out.println("Thread 1 is waiting...");lock.wait(); // 线程1等待,释放锁System.out.println("Thread 1 is awakened!");} catch (InterruptedException e) {e.printStackTrace();}}});Thread notifyingThread = new Thread(() -> {synchronized (lock) {System.out.println("Thread 2 is notifying...");lock.notify(); // 唤醒等待的线程1}});waitingThread.start();notifyingThread.start();}}在上述例子中,Thread 1 调用了lock.wait() 进入等待状态,而Thread 2 调用了lock.notify() 来唤醒等待的Thread 1。

java锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)

java锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)

java锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)wait是指在⼀个已经进⼊了同步锁的线程内,让⾃⼰暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运⾏,只有其他线程调⽤了notify⽅法(notify并不释放锁,只是告诉调⽤过wait⽅法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别⼈⼿⾥,别⼈还没释放),调⽤wait⽅法的⼀个或多个线程就会解除wait状态,重新参与竞争对象锁,程序如果可以再次得到锁,就可以继续向下运⾏。

1)wait()、notify()和notifyAll()⽅法是本地⽅法,并且为final⽅法,⽆法被重写。

 2)当前线程必须拥有此对象的monitor(即锁),才能调⽤某个对象的wait()⽅法能让当前线程阻塞,(这种阻塞是通过提前释放synchronized锁,重新去请求锁导致的阻塞,这种请求必须有其他线程通过notify()或者notifyAll()唤醒重新竞争获得锁) 3)调⽤某个对象的notify()⽅法能够唤醒⼀个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中⼀个线程;(notify()或者notifyAll()⽅法并不是真正释放锁,必须等到synchronized⽅法或者语法块执⾏完才真正释放锁) 4)调⽤notifyAll()⽅法能够唤醒所有正在等待这个对象的monitor的线程,唤醒的线程获得锁的概率是随机的,取决于cpu 调度例⼦1(错误使⽤导致线程阻塞):三个线程,线程3先拥有sum对象的锁,然后通过sum.notify()⽅法通知等待sum锁的线程去获得锁,但是这个时候线程1,2并没有处于wait()导致的阻塞状态,⽽是在synchronized⽅法块处阻塞了,所以,这次notify()根本没有通知到线程1,2。

然后线程3正常结束,释放掉sum锁,这个时候,线程1就⽴刻获得了sum对象的锁(通过synchronized获得),然后调⽤sum.wait()⽅法释放掉sum的锁,线程2随后获得了sum对象的线程锁(通过synchronized获得),这个时候线程1,2都处于阻塞状态,但是悲催的是,这之后再也没有线程主动调⽤sum.notify()或者notifyAll()⽅法显⽰唤醒这两个线程,所以程序阻塞1. public class CyclicBarrierTest {2.3. public static void main(String[] args) throws Exception {4. final Sum sum=new Sum();5.6. new Thread(new Runnable() {7. @Override8. public void run() {9. try {10. synchronized (sum) {11. System.out.println("thread3 get lock");12. sum.sum();13. sum.notifyAll(); //此时唤醒没有作⽤,没有线程等待14. Thread.sleep(2000);15. System.out.println("thread3 really release lock");16. }17.18. } catch (Exception e) {19. e.printStackTrace();20. }21. }22. }).start();23.24. new Thread(new Runnable() {25. @Override26. public void run() {27. try {28. synchronized (sum) {29. System.out.println("thread1 get lock");30. sum.wait();//主动释放掉sum对象锁31. System.out.println(sum.total);32. System.out.println("thread1 release lock");33. }34. } catch (Exception e) {35. e.printStackTrace();36. }37. }38. }).start();39.40. new Thread(new Runnable() {41. @Override42. public void run() {43. try {44. synchronized (sum) {45. System.out.println("thread2 get lock");46. sum.wait(); //释放sum的对象锁,等待其他对象唤醒(其他对象释放sum锁)47. System.out.println(sum.total);48. System.out.println("thread2 release lock");49. }50. } catch (Exception e) {51. e.printStackTrace();52. }53. }54. }).start();55. }56.57. }58.59. class Sum{60. public Integer total=0;61.62. public void sum() throws Exception{63. total=100;64. Thread.sleep(5000);65. }66.67. }运⾏结果:1. thread3 get lock2. thread3 really release lock3. thread2 get lock4. thread1 get lock5. //程序后⾯⼀直阻塞例⼦2:还是上⾯程序,顺序不同,把线程3放到最下⾯。

Java中wait()和notify()方法的使用

Java中wait()和notify()方法的使用

Java中wait()和notify()⽅法的使⽤1. wait⽅法和notify⽅法这两个⽅法,包括notifyAll⽅法,都是Object类中的⽅法。

在Java API中,wait⽅法的定义如下:public final void wait()throwsCauses the current thread to wait until another thread invokes the method or the method for this object. In other words, thismethod behaves exactly as if it simply performs the call wait(0).The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. Thethread then waits until it can re-obtain ownership of the monitor and resumes execution.As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in aloop:synchronized (obj) {while (<condition does not hold>)obj.wait();... // Perform action appropriate to condition}This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.在 Java 中可以⽤ wait、notify 和 notifyAll 来实现线程间的通信。

Java wait() notify()方法使用实例讲解

Java wait() notify()方法使用实例讲解

1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。

2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁,或者叫管程)3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程;4)调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程;在Java中,是没有类似于PV操作、进程互斥等相关的方法的。

JAVA的进程同步是通过synchronized()来实现的,需要说明的是,Java的synchronized()方法类似于操作系统概念中的互斥内存块,在Java中的Object类对象中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现Java中简单的同步、互斥操作。

明白这个原理,就能理解为什么synchronized(this)与synchronized(static XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字代表类的一个对象,所以其内存锁是针对相同对象的互斥操作,而static成员属于类专有,其内存空间为该类所有成员共有,这就导致synchronized()对static成员加锁,相当于对类加锁,也就是在该类的所有成员间实现互斥,在同一时间只有一个线程可访问该类的实例。

如果需要在线程间相互唤醒就需要借助Object类的wait()方法及nofity()方法。

说了这么一堆,可能似懂非懂,那么接下来用一个例子来说明问题,用多线程实现连续的1,2,1,2,1,2,1,2,1,2输出。

[java]view plain copy1.class NumberPrint implements Runnable{2.private int number;3.public byte res[];4.public static int count = 5;5.public NumberPrint(int number, byte a[]){6.this.number = number;7. res = a;8. }9.public void run(){10.synchronized (res){11.while(count-- > 0){12.try {13. res.notify();//唤醒等待res资源的线程,把锁交给线程(该同步锁执行完毕自动释放锁)14. System.out.println(" "+number);15. res.wait();//释放CPU控制权,释放res的锁,本线程阻塞,等待被唤醒。

wait()与notify()

wait()与notify()

wait()与notify()⼀,前⾔简单画了⼀下线程的流程图,只是⼀个⼤概。

如图所⽰,线程有多种状态,那么不同状态之间是如何切换的,下⾯主要总结关于wait()和notify()的使⽤。

⼆,wait()wait()和notify()都是定义在Object类中,为什么如此设计。

因为synchronized中的这把锁可以是任意对象,所以任意对象都可以调⽤wait()和notify(),并且只有同⼀把锁才能对线程进⾏操作,不同锁之间是不可以相互操作的,所以wait和notify属于Object。

请看如下API⽂档说明。

wait()提供三种构造⽅法,但前两种最为常⽤,wait()是让线程⼀直处于等待状态,直到⼿动唤醒,⽽wait(long timeout)可以指定等待时间,之后会⾃动唤醒。

调⽤wait⽅法可以让当前线程进⼊等待唤醒状态,该线程会处于等待唤醒状态直到另⼀个线程调⽤了object对象的notify⽅法或者notifyAll⽅法。

三,notify()notify()唤醒等待的线程,如果监视器种只有⼀个等待线程,使⽤notify()可以唤醒。

但是如果有多条线程notify()是随机唤醒其中⼀条线程,与之对应的就是notifyAll()就是唤醒所有等待的线程,请看下⾯实例代码。

案例:定义两条线程,分别让其线程等待,及线程唤醒。

1,定义线程。

public class SetTarget implements Runnable{private Demo demo;public SetTarget(Demo demo) {this.demo = demo;}@Overridepublic void run() {demo.set();}}public class GetTarget implements Runnable {private Demo demo;public GetTarget(Demo demo) {this.demo = demo;}@Overridepublic void run() {demo.get();}}2,编写main⽅法。

java多线程同步waitnotifysynchronized

java多线程同步waitnotifysynchronized

JAVA 多线程同步wait 、notify 、synchronized1 wait 方法:该方法属于Object 的方法,wait 方法的作用是使得当前调用wait 方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait 所在的代码块的锁,并在其他线程调用notify 或者notifyAll 方法时恢复到竞争锁状态(一旦获得锁就恢复执行)。

调用wait 方法需要注意几点:第一点:wait 被调用的时候必须在拥有锁(即synchronized 修饰的)的代码块中。

第二点:恢复执行后,从wait 的下一条语句开始执行,因而wait 方法总是应当在while 循环中调用,以免出现恢复执行后继续执行的条件不满足却继续执行的情况。

第三点:若wait 方法参数中带时间,则除了notify 和notifyAll 被调用能激活处于wait 状态(等待状态)的线程进入锁竞争外,在其他线程中interrupt 它或者参数时间到了之后,该线程也将被激活到竞争状态。

第四点:wait 方法被调用的线程必须获得之前执行到wait 时释放掉的锁重新获得才能够恢复执行。

2 notify 方法和notifyAll 方法:notify 方法通知调用了wait 方法,但是尚未激活的一个线程进入线程调度队列(即进入锁竞争),注意不是立即执行。

并且具体是哪一个线程不能保证。

另外一点就是被唤醒的这个线程一定是在等待wait 所释放的锁。

notifyAll 方法则唤醒所有调用了wait 方法,尚未激活的进程进入竞争队列。

3 synchronized 关键字:第一点:synchronized 用来标识一个普通方法时,表示一个线程要执行该方法,必须取得该方法所在的对象的锁。

第二点:synchronized 用来标识一个静态方法时,表示一个线程要执行该方法,必须获得该方法所在的类的类锁。

第三点:synchronized 修饰一个代码块。

java使用wait(),notify(),notifyAll()实现等待通知机制

java使用wait(),notify(),notifyAll()实现等待通知机制

java使⽤wait(),notify(),notifyAll()实现等待通知机制public class WaitNotify {static boolean flag=true;static Object lock=new Object();static class Wait implements Runnable{@Overridepublic void run() {synchronized (lock){while(flag){try{System.out.println(Thread.currentThread()+" flag is true. wait " +"@ "+new SimpleDateFormat("HH:mm:ss").format(new Date()));lock.wait();}catch (InterruptedException e){}}}System.out.println(Thread.currentThread()+" flag is false.running " +"@"+new SimpleDateFormat("HH:mm:ss").format(new Date()));}}static class Notify implements Runnable{@Overridepublic void run() {synchronized (lock) {System.out.println(Thread.currentThread() + " hold lock. notify " +"@ " + new SimpleDateFormat("HH:mm:ss").format(new Date()));lock.notifyAll();flag = false;SleepUtils.second(5);}synchronized (lock){System.out.println(String.format(Thread.currentThread() + " hold lock again. sleep " +"@" + new SimpleDateFormat("HH:mm:ss").format(new Date())));SleepUtils.second(5);}}}public static void main(String[] args) {Thread waitThread=new Thread(new Wait(),"WaitThread");waitThread.start();try {TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){}Thread notifyThread=new Thread(new Notify(),"NotifyThread");notifyThread.start();}}程序执⾏结果:Thread[WaitThread,5,main] flag is true. wait @ 14:41:12Thread[NotifyThread,5,main] hold lock. notify @ 14:41:13Thread[NotifyThread,5,main] hold lock again. sleep @14:41:18Thread[WaitThread,5,main] flag is false.running @14:41:231.使⽤wait(),notify(),notifyAll()⽅法之前,要获取同⼀个对象的锁。

高级应用java多线程设计模式详解之二wait()notify()

高级应用java多线程设计模式详解之二wait()notify()

⾼级应⽤java多线程设计模式详解之⼆wait()notify()wait()/notify() 通常,多线程之间需要协调⼯作。

例如,浏览器的⼀个显⽰图⽚的线程 displayThread想要执⾏显⽰图⽚的任务,必须等待下载线程downloadThread将该图⽚下载完毕。

如果图⽚还没有下载完,displayThread能暂停,当downloadThread完成了任务后,再通知displayThread“图⽚准备完毕,能显⽰了”,这时,displayThread继续执⾏。

以上逻辑简单的说就是:如果条件不满⾜,则等待。

当条件满⾜时,等待该条件的线程将被唤醒。

在Java中,这个机制的实现依赖于wait/notify。

等待机制和锁机制是密切关联的。

例如: synchronized(obj) { while(!condition) obj.doSomething(); } 当线程A获得了obj锁后,发现条件condition不满⾜,⽆法继续下⼀处理,于是线程A就wait()。

在另⼀线程B中,如果B更改了某些条件,使得线程A的condition条件满⾜了,就能唤醒线程A: synchronized(obj) { condition = true; obj.notify(); } 需要注意的概念是:需要注意的概念是: # 调⽤obj的wait(), notify()⽅法前,必须获得obj锁,也就是必须写在synchronized(obj) 代码段内。

# 调⽤obj.wait()后,线程A就释放了obj的锁,否则线程B⽆法获得obj锁,也就⽆法在synchronized(obj) 代码段内唤醒A。

# 当obj.wait()⽅法返回后,线程A需要再次获得obj锁,才能继续执⾏。

# 如果A1,A2,A3都在obj.wait(),则B调⽤obj.notify()只能唤醒A1,A2,A3中的⼀个(具体哪⼀个由JVM决定)。

java synchronized wait notify 实例

java synchronized wait notify 实例
public class ProducerConsumerExample {
private final Object lock = new Object();
private int value = 0;
//生产者线程
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 100; i++) {
synchronized (lock) {
value = i;
System.out.println("生产者生产了: " + value);
lock.notify(); //通知消费者有新的数据可用
lock.wait(); //等待消费者消费数据后再次通知
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
public static void main(ห้องสมุดไป่ตู้tring[] args) {
ProducerConsumerExample pc = new ProducerConsumerExample();
pc.producer.start(); //启动生产者线程
Thread.currentThread().interrupt();
}
});
//消费者线程
Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 100; i++) {

Javawait和notifyAll的使用,简单的阻塞队列实现

Javawait和notifyAll的使用,简单的阻塞队列实现

Javawait和notifyAll的使⽤,简单的阻塞队列实现wait,会使调⽤的线程进⼊等待状态,会释放所持有的对象锁(调⽤的时候也必须先获取到锁,否则会抛出异常IllegalMonitorStateException)notifyAll、notify,会去唤醒应当前对象⽽等待的线程,(调⽤的时候也必须先获取到锁,否则会抛出异常 IllegalMonitorStateException)顺便也记录⼀下join⽅法,调⽤join⽅法,会使当前线程进⼊等待,如果没有设置等待时间,就会等待另⼀个线程执⾏完成才返回(ps:调⽤join⽅法并不⼀定⽴刻执⾏另⼀个线程,只是当前线程进⼊等待,然后切换下⼀个线程)1import java.util.concurrent.atomic.AtomicInteger;23/**4 * @author lhd5*/6public class BlockQueue {78/**9 * ⽣产者锁对象10*/11private final Object addLock = new Object();1213/**14 * 消费者锁对象15*/16private final Object deleteLock = new Object();1718/**19 * 队列总⼤⼩20*/21private final Integer size = 30;2223/**24 * 数据存放25*/26private Object[] queue = new Object[size];2728/**29 * 存放的数量,使⽤AtomicInteger是因为普通的int递增递减操作会存在⾮原⼦性的问题,会使数量异常30*/31private AtomicInteger count = new AtomicInteger(0);3233/**34 * ⽣产35 * @param o 对象36*/37public void add(Object o) {38//获取⽣产锁,wait⽅法必须获取到对象锁后才可以调⽤,否则抛出异常39synchronized (addLock){4041//判断是否超过队列⼤⼩,超过则进⼊等待42while (count.get() >= size){43try {44 addLock.wait();45 } catch (InterruptedException e) {46 e.printStackTrace();47 }48 }49//存放⼀个50 queue[count.get()] = o;51//递增52int i = count.incrementAndGet();53//打印⼀下⽇志54 String name = Thread.currentThread().getName();55 System.out.println(name + "⽣产了⼀个,现有数量" + i);56 }57//如果队列有数据,则调⽤notifyAll唤醒消费者58if (count.get() >= 1){59//notifyAll、notify都需要先获取对象锁,否则会抛出异常60synchronized (deleteLock){61 deleteLock.notifyAll();62 }63 }6465 }6667/**68 * 消费69 * @return70*/71public Object poll(){73//先获取对象锁,和⽣产者类似74synchronized (deleteLock){75//队列⾥没有数据则等待76while (count.get() <= 0){77try {78 deleteLock.wait();79 } catch (InterruptedException e) {80 e.printStackTrace();81 }82 }83//获取数据84 o = queue[count.get()];85//递减86int i = count.decrementAndGet();87 String name = Thread.currentThread().getName();88 System.out.println(name + "消费了⼀个,现有数量" + i);89 }90//如果队列没有满,则可以唤醒⽣产者91if (count.get() < size){92//需要先获取到锁93synchronized (addLock){94 addLock.notifyAll();95 }96 }97return o;98 }99100/**101 * 简单的测试102 * @param args103*/104public static void main(String[] args) {105 BlockQueue blockQueue = new BlockQueue();106 Thread t1 = new Thread(()-> {while (true){blockQueue.add(new Object());}}); 107 Thread t2 = new Thread(()-> {while (true){blockQueue.add(new Object());}}); 108 Thread t3 = new Thread(()-> {while (true){blockQueue.add(new Object());}}); 109 Thread t4 = new Thread(()-> {while (true){blockQueue.poll();}});110 Thread t5 = new Thread(()-> {while (true){blockQueue.poll();}});111 Thread t6 = new Thread(()-> {while (true){blockQueue.poll();}});112 t1.start();113 t2.start();114 t3.start();115 t4.start();116 t5.start();117 t6.start();118 }119120 }效果:其实这个递增递减操作和打印操作也不是原⼦操作,依次打印线程1,2,31/**2 * @author lhd3*/4public class JoinTest {567public static void main(String[] args) throws InterruptedException {8 Thread t1 = new Thread(() -> System.out.println(1));9 Thread t2 = new Thread(()-> System.out.println(2));10 Thread t3 = new Thread(()-> System.out.println(3));1113 t1.join(); 1415 t2.start();16 t2.join(); 1718 t3.start();19 t3.join(); 2021 }2223 }。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
至少说明了一点,wait后如果没有其它线程将它notify,是绝不可能重新启动的。不可能因为目前没有线程占用CPU,某一个正在等待的线程就自动重启。
下面,我再把它改一下,写四个线程,分别是
T1 wait()
T2 notify()
T3 notify()
T4 wait()
public class ThreadF {
是不能同时被两个线程用来进入synchronized中的。这就是线程同步。
废话不多说,先用通俗一点的语言来解释一下wait()和notify():
wait()意思是说,我等会儿再用这把锁,CPU也让给你们,我先休息一会儿!
notify()意思是说,我用完了,你们谁用?
也就是说,wait()会让出对象锁,同时,当前线程休眠,等待被唤醒,如果不被唤醒,ቤተ መጻሕፍቲ ባይዱ一直等在那儿。
T3 start!
T3 end!
T4 start!
执行流程:
T1启动,wait,让出CPU和锁,T2得以启动。T2启动,并唤醒一个线程,自己继续执行。被唤醒的线程,也就是T1等待启动机会。
T2执行完,T1抢到了CPU,执行,并结束。
这时,只剩下T3和T4,在此时,两个线程的机会均等。
但是,T3抢到了CPU,于是它执行了,而且唤醒了线程,虽然此时并没有线程休眠。说白了,它浪费了一次notify。T3顺利执行完。
}
}
};
t1.start();
t2.start();
t3.start();
t4.start();
}
}
首先,大家知道,线程启动的顺序,和代码的先后顺序,理论上是没有关系的!
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T4 end!");
所以说,T2和T3由于是写的notify,它们的start和end总是成对出现。而T1和T4由于是写的wait,它们start后,下一个绝不可能是它的end。
最后再提醒一下,我们的wait和notify是针对同一个object的,而非线程。我们这一篇都在讲对象锁,而不是线程。
顺便说一下,如果没有线程在wait,调用notify是不会有什么问题的,就像这样:
}
}
};
Thread t2 = new Thread() {
public void run()
{
synchronized (object) {
T1执行完,T4获得CPU,启动,wait,T3获得了锁和CPU,执行,宣布锁用完了,其它线程可以用了,然后继续执行,T3执行完,已经被唤醒并且等待已久的T4
得到CPU,执行。
2、不能执行结束,有线程由于没有其它线程唤醒,一直在等待中:
T1 start!
T2 start!
T2 end!
T1 end!
}
};
Thread t3 = new Thread() {
public void run()
{
synchronized (object) {
System.out.println("T3 start!");
synchronized (object) {
System.out.println("T1 start!");
try {
object.wait();
这时,终于轮到了T4,它启动了,wait了,但是,后面已经没有线程了,它的wait永远不会有线程帮它notify了!
于是,它就这么等着!
请仔细看执行流程,看懂,再自己做一下试验。
仔看看,你会看到,凡是当前线程的run方法里面写了notify,有了start马上就会end,而如果是写的wait,有了start,下一个绝对不是输出这个线程的end。
那么,如果两个线程都写wait没有线程写notify会有什么现象呢?试一下就知道了。
结果是,
T1 start!
T2 start!
然后就是一直等待!
道理很显然,T1先启动,然后wait了,T2获得了锁和CPU,在没有其它线程与它竞争的情况下,T2执行了,然后也wait了。
在这里,两个线程都在等待,没有其它线程将它们notify,所以结果就是无休止地等下去!
{
synchronized (object) {
System.out.println("T2 start!");
object.notify();
System.out.println("T2 end!");
{
synchronized (object) {
System.out.println("T4 start!");
try {
object.wait();
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1 end!");
}
}
};
Thread t2 = new Thread() {
public void run()
notify()并不会让当前线程休眠,但会唤醒休眠的线程。
先看第一个例子!
public class ThreadF {
public static void main(String[] args) {
final Object object = new Object();
Thread t1 = new Thread() {
public void run()
{
synchronized (object) {
System.out.println("T1 start!");
try {
我摘选了两种情况的输出结果,仅供参考:
1、可以执行结束的情况:
T1 start!
T2 start!
T2 end!
T1 end!
T4 start!
T3 start!
T3 end!
T4 end!
执行流程是:
T1启动,wait,T2获得锁和CPU,T2宣布锁用完了其它线程可以用了,然后继续执行,T2执行完,T1被刚才T2唤醒后,等待T2执行完后,抢到了CPU,T1执行,
object.notify();
System.out.println("T3 end!");
}
}
};
Thread t4 = new Thread() {
public void run()
}
}
};
t1.start();
t2.start();
}
}
这第一个例子很简单,写了两个线程(分别是两个类,两个run方法)。
两个run方法之间没有关系,但是,他们都用了同一个object!
值得一提的是,再强调一遍:
wait会让出CPU而notify不会,notify重在于通知使用object的对象“我用完了!”,wait重在通知其它同用一个object的线程“我暂时不用了”并且让出CPUT。
所以说,看上面的顺序,
T2 start!
T2 end!
是连续的,说明它并没有因调用了notify而暂停!
public class ThreadG {
public static void main(String[] args) {
final Object object = new Object();
JAVA线程同步中wait()和notify()简洁例子
搞懂这两个的用法之前,请你务必搞懂线程同步的道理,否则,下面这一大篇你应该是看不懂的。
wait()和notify()一系列的方法,是属于对象的,不是属于线程的。它们用在线程同步时,synchronized语句块中。
我们都知道,在synchronized语句块中,同一个对象,一个线程在执行完这一块代码之前,另一个线程,如果传进来的是同一个object,是不能进入这个语句块的。也就是说,同一个对象
仔细看,T1里面主要写了个wait(),而T2里面主要写了个notify()。
我们看到执行结果是:
T1 start!
T2 start!
T2 end!
T1 end!
流程可以这样解释:
T1启动,让出锁,让出CPU,T2获得CPU,启动,唤醒使用了object的休眠的线程,T1被唤醒后等待启动,T2继续执行,T2执行完,T1获得CPU后继续执行。
public static void main(String[] args) {
final Object object = new Object();
Thread t1 = new Thread() {
public void run()
{
System.out.println("T2 start!");
object.notify();
System.out.println("T2 end!");
}
比如我这儿写的是按T1-T2-T3-T4的先后顺序先后start(),但实际上谁先启动,是有一定几率的。
相关文档
最新文档