这篇文章主要为大家详细介绍了Java使用wait() notify()方法操作共享资源,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
Java多个线程共享资源;
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输出。
package com.study.thread; /** * 多线程 * @ClassName: PrintFile * @date 2017年10月10日 下午4:05:04 */ public class PrintFile implements Runnable{ //当前线程id private int id ; //共享资源 public byte[] res ; //如果类里写了有参构造器,而任然想保留无参数构造方法,则必须显式的写出该方法。 public PrintFile() { super(); // System.out.println("我是构造器"); } public PrintFile(int id, byte[] res) { //构造器中使用super()/this(),必须放在第一行。 this(); this.id = id; this.res = res; } //静态计数器 public static int count = 5; @Override public void run() { synchronized (res) { while(count-->=0){ try { res.notify();//唤醒其他线程中的某一个(唤醒等待res的其他线程,当前线程执行完后要释放锁) System.out.println("当前线程id值:"+id); res.wait();//当前线程阻塞,等待被唤醒 System.out.println("现在执行的线程是"+Thread.currentThread().getName()+",--wait()后的代码继续执行:"+id); } catch (InterruptedException e) { e.printStackTrace(); } } return; } } }
测试:
package com.study.thread; public class PrintFileTest { public static void main(String[] args) { byte[] res = new byte[]{0,1,2};//共享资源 PrintFile p1 = new PrintFile(1, res); PrintFile p2 = new PrintFile(2, res); Thread t1 = new Thread(p1, "a"); Thread t2 = new Thread(p2, "b"); t1.start(); t2.start(); } }
结果:
当前线程id值:1
当前线程id值:2
现在执行的线程是a,--wait()后的代码继续执行:1
当前线程id值:1
现在执行的线程是b,--wait()后的代码继续执行:2
当前线程id值:2
现在执行的线程是a,--wait()后的代码继续执行:1
当前线程id值:1
现在执行的线程是b,--wait()后的代码继续执行:2
当前线程id值:2
现在执行的线程是a,--wait()后的代码继续执行:1
下面解释为什么会出现这样的结果:
首先1、2号线程启动,这里假设1号线程先运行run方法获得资源(实际上是不确定的),获得对象a的锁,进入while循环(用于控制输出几轮):
1、此时对象调用它的唤醒方法notify(),意思是这个同步块执行完后它要释放锁,把锁交给等待a资源的线程;
2、输出1;
3、该对象执行等待方法,意思是此时此刻起拥有这个对象锁的线程(也就是这里的1号线程)释放CPU控制权,释放锁,并且线程进入阻塞状态,后面的代码暂时不执行,因未执行完同步块,所以1也没起作用;
4、在这之前的某时刻线程2运行run方法,但苦于没有获得a对象的锁,所以无法继续运行,但3步骤之后,它获得了a的锁,此时执行a的唤醒方法notify(),同理,意思是这个同步块执行完后它要释放锁,把锁交给等待a资源的线程;
5、输出2;
6、执行a的等待方法,意思是此时此刻起拥有这个对象锁的线程(也就是这里的2号线程)释放CPU控制权,释放锁,并且线程进入阻塞状态,后面的代码暂时不执行,因未执行完同步块,所以2号线程的4步骤的唤醒方法也没起作用;
7、此时1号线程执行到3步骤,发现对象锁没有被使用,所以继续执行3步骤中wait方法后面的代码,于是输出:------线程1获得锁,wait()后的代码继续运行:1;
8、此时while循环满足条件,继续执行,所以,再执行1号线程的唤醒方法,意思是这个同步块执行完后它要释放锁;
9、输出1;
10、执行等待方法,线程1阻塞,释放资源锁;
11、此时线程2又获得了锁,执行到步骤6,继续执行wait方法后面的代码,所以输出:------线程2获得锁,wait()后的代码继续运行:2;
12、继续执行while循环,输出2;
··· ···
通过上述步骤,相信大家已经明白这两个方法的使用了,但该程序还存在一个问题,当while循环不满足条件时,肯定会有线程还在等待资源,所以主线程一直不会终止。当然这个程序的目的仅仅为了给大家演示这两个方法怎么用。
总结:
wait()方法与notify()必须要与synchronized(resource)一起使用。也就是wait与notify针对已经获取了resource锁的线程进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来说wait()线程在获取对象锁后,主动释放CPU控制权,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的释放操作。【因此,我们可以发现,wait和notify方法均可释放对象的锁,但wait同时释放CPU控制权,即它后面的代码停止执行,线程进入阻塞状态,而notify方法不立刻释放CPU控制权,而是在相应的synchronized(){}语句块执行结束,再自动释放锁。】释放锁后,JVM会在等待resoure的线程中选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制,而在同步块中的Thread.sleep()方法并不释放锁,仅释放CPU控制权。
以上是Java如何使用wait()与notify()方法操作共享资源的实例的详细内容。更多信息请关注PHP中文网其他相关文章!

本文讨论了使用Maven和Gradle进行Java项目管理,构建自动化和依赖性解决方案,以比较其方法和优化策略。

本文使用Maven和Gradle之类的工具讨论了具有适当的版本控制和依赖关系管理的自定义Java库(JAR文件)的创建和使用。

本文讨论了使用咖啡因和Guava缓存在Java中实施多层缓存以提高应用程序性能。它涵盖设置,集成和绩效优势,以及配置和驱逐政策管理最佳PRA

本文讨论了使用JPA进行对象相关映射,并具有高级功能,例如缓存和懒惰加载。它涵盖了设置,实体映射和优化性能的最佳实践,同时突出潜在的陷阱。[159个字符]

Java的类上载涉及使用带有引导,扩展程序和应用程序类负载器的分层系统加载,链接和初始化类。父代授权模型确保首先加载核心类别,从而影响自定义类LOA


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

禅工作室 13.0.1
功能强大的PHP集成开发环境

WebStorm Mac版
好用的JavaScript开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)