线程间通信
来源:互联网 发布:包工头app软件下载 编辑:程序博客网 时间:2024/06/03 16:34
之前的售票程序或者银行取钱例子中,所有线程执行的代码都是一样的。
线程间通信:A线程往里存,B线程往外取。
AB线程的动作不一致,也就需要有两个run方法。两个run方法就要存在两个线程当中。什么时候可以取,什么时候可以存,这就需要线程之间的通信。
例子:一个写入线程负责写,读取线程负责读,两者操作的是同一个资源,但是操作的动作是不同的。这时就要进行线程间通信。
package fighting;public class ThreadCommunication {/** * 线程间通讯:解决安全问题(要用同一个锁) * 其实就是多个线程在操作同一个资源,但是操作的动作不同。这样就需要通讯。 * * 同步以后也会发生一种情况: * 就是输入线程往里存了一个,输出线程可能会执行了多次,取了多次, * 这样输出线程就会取到多次相同的值。这需要等待唤醒机制来解决。 * 等待唤醒机制:就是需要一个资源的flag。 * * wait()和notify(),notifyAll() * 这几个方法都是用在同步中,要对持有监视器(也就是锁)的线程操作。 * * 为什么线程用到的方法wait()和notify(),notifyAll()会定义在Oject类中,而不是定义在Thread类中? * 因为这些方法在操作同步的线程时,都必须要标识它们所操作线程持有的锁。 * 只有同一个锁上的被等待线程,可以被同一个锁上nofify唤醒。 * 不可以对不同锁中的线程唤醒。 * 也就是说,等待和唤醒必须是同一个锁。 * 而锁可以使任意对象,所以可以被任意对象调用的方法要定义在Oject类中。 * */public static void main(String[] args) {Resource r = new Resource();InputThread in = new InputThread(r);OutputThread out = new OutputThread(r);new Thread(in).start();new Thread(out).start();}}//线程要操作的资源class Resource{String name;String sex;boolean flag = false;//等待唤醒机制的标志位}//输入的线程class InputThread implements Runnable{private Resource r;InputThread(Resource r){this.r=r;}public void run() {//同步synchronize写在run方法,就变成了单线程了,一个线程进来,其他线程就进不来了boolean b=true;int i=0;while(true){/** * 这里同步锁用了r,是因为InputThread和OutputThread两个线程操作的都是一个r。 * 这里也可以用InputThread.class或OutputThread.class或Resource.class, * 只要在内不能中是唯一的就可以,但是这样显得牵强。 */synchronized (r) {if(r.flag){//flag为True,说明已经有资源,不用再存,线程等待try {r.wait();//知识点:等待的线程存在内存线程池中,notify唤醒的都是线程池中的线程。 //注意:wait和notify方法必须标明是哪个锁,而且这个锁要和同步的锁是一个才可以。} catch (InterruptedException e) {e.printStackTrace();}}if(b){r.name="张三"+(i++);r.sex="男";b=false;}else{r.name="李四"+(i++);r.sex="女";b=true;}r.flag=true;r.notify();//唤醒等待的一个线程。还有一个方法notifyAll,唤醒所有等待的线程}}}}//取走的线程class OutputThread implements Runnable{private Resource r;OutputThread(Resource r){this.r=r;}public void run() {while(true){synchronized (r) {if(!r.flag){//flag为false,说明没有资源,不能取,线程等待try {r.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(r.name+"..."+r.sex);r.flag=false;r.notify();}}}}
代码优化:把资源类Resource的成员私有化。
package fighting;public class ThreadCommunication {/** * 代码优化:把资源私有化 */public static void main(String[] args) {Resource r = new Resource();InputThread in = new InputThread(r);OutputThread out = new OutputThread(r);new Thread(in).start();new Thread(out).start();}}//线程要操作的资源class Resource{private String name;private String sex;private boolean flag = false;//等待唤醒机制的标志位public synchronized void set(String name,String sex){if(flag){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.name=name;//--->如果线程在执行完上一句,在这里被其他线程抢走了执行权,则这里会出现安全问题,所以这个方法需要同步this.sex=sex;flag=true;this.notify();//有资源了,将其他线程唤醒,通知可以取资源了}public synchronized void out(){if(!flag){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(name+"..."+sex);flag=false;this.notify();//这句唤醒要写在资源里面,如果线程里面, //就会报错IllegalMonitorStateException(意思是当前线程不是此对象监视器的所有者)。}}//输入的线程class InputThread implements Runnable{private Resource r;InputThread(Resource r){this.r=r;}public void run() {//同步synchronize写在run方法,就变成了单线程了,一个线程进来,其他线程就进不来了boolean b=true;int i=0;while(true){if(b){r.set("张三"+(i++), "男");b=false;}else{r.set("李四"+(i++), "女");b=true;}//r.notify();//这句唤醒如果这里,就会报错IllegalMonitorStateException(意思是当前线程不是此对象监视器的所有者), //因为同步是在资源类的方法上实现的,程序执行到这的时候,已经从同步方法里出来了。 //当前线程是InputThread这个线程,同步锁的所有者是Resource,}}}//取走的线程class OutputThread implements Runnable{private Resource r;OutputThread(Resource r){this.r=r;}public void run() {while(true){r.out();//r.notify();}}}
- 线程同步--线程间通信
- 线程同步--线程间通信
- JAVASE线程---线程间通信
- JAVA线程-线程间通信
- 线程3:线程间通信
- 线程与线程间通信
- 线程间通信
- c#线程间通信
- VC 线程间通信
- 线程间通信 ManualResetEvent
- java 线程间通信
- android线程间通信
- VC 线程间通信
- 线程间通信方式
- QT---线程间通信
- Android线程间通信
- 线程间的通信
- linux线程间通信
- win8系统快捷键
- JQuery实现表格的相同单元格合并的三种方法
- iperf测试throughput
- hdu3660
- Oracle查询中rownum与Order by查询的关系(取数据的前几条)
- 线程间通信
- java读取文件夹下所有文件并替换文件每一行中指定的字符串
- Tsung的安装和使用
- dispatchTouchEvent/dispatchTouchEvent/onInterceptTouchEvent调用时机
- Spring2.5教程:3、Bean
- Phonegap-----Media
- POJ-1191-棋盘分割
- 中文转拼音
- .C与.CPP 在编译时的区别