`

java线程之间通信<四>

    博客分类:
  • java
 
阅读更多
  
  在同步方法中,线程间的通信主要依靠wait(),notify(),notifyAall(),来实现。

   这三个方法必须在synconized 代码块中使用。
下面这段话引用网上:
引用
  wait()方法使当前线程暂停执行并释放对象锁标志,让其他线程可以进入Synchronized数据块,当前线程被放入对象等待池中。当调用 notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志等待池中的线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。
   notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中


下面用代码测验:

程序主要实现2个线程之间通信,实现线程访问的对象的实例变量在0,1之间交替出现。
代码如下:


package com.xxg.Notify;

public class Model {
	
	 public int number;
	 
	public synchronized void add(){
		
		if(number!=0)
		{
		  try {
			wait();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		}
		number++;

		System.out.println("【当前线程】==="+Thread.currentThread().getName()+"===="+number+"-----当前对应的对象锁为----"+this);
		notify();
		
	}
public synchronized void decrease(){
		
		if(number==0)
		{
		  try {
			wait();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		}
		number--;
		
		System.out.println("【当前线程】==="+Thread.currentThread().getName()+"===="+number+"-----当前对应的对象锁为----"+this);
		notify();
		
	}
  
}




//增加变量值线程
package com.xxg.Notify;

public class ThIncrease extends Thread {
	public Model in;
	
	 public ThIncrease(Model in)
	 {
		 this.in = in;
	 }
	public void run() {
	 for(int i=0;i<10;i++)	 
	 {   
		 try {
		Thread.sleep(1000);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
		 in.add(); //调用自加方法
	 }
	 }
}

//===========================实现自减线程=========================
package com.xxg.Notify;

public class ThDecrease extends Thread {
	public Model in;
	
	 public ThDecrease(Model in)
	 {
		 this.in = in;
	 }
	public void run() {
	 for(int i=0;i<10;i++)	 
	 {   
		 try {
		Thread.sleep(1000);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
		 in.decrease();
	 }
	 }
		 
	}


//==========================测试代码=============================
package com.xxg.Notify;

public class Test {

	
	public static void main(String[] args) {
	
		Model mo = new Model();
		Model mo1 = new Model();
	
		Thread t1 = new ThDecrease(mo);
		Thread t2 = new ThIncrease(mo);
		t1.start();
		t2.start();
		
	}

}
//=========================测试结果==============================

【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-0====0-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-0====0-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-0====0-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-0====0-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-0====0-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-0====0-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-0====0-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-0====0-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-0====0-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
【当前线程】===Thread-0====0-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459



通过wait()和notify()方法实现了线程通信,1,和0交替出现。

注意:如果把测试代码
Thread t1 = new ThDecrease(mo);
Thread t2 = new ThIncrease(mo);
改成
Thread t1 = new ThDecrease(mo);
Thread t2 = new ThIncrease(mo1);
就无法实现线程通信了,测试结果为:
【当前线程】===Thread-1====1-----当前对应的对象锁为----com.xxg.Notify.Model@1bc4459
只出现一条结果,就出现死锁了。
我的理解是这样的不知道对不,还望大神指点下。
理解:由于这里产生了mo,mo1,两个不同的对象锁,那么mo1.notif()方法是不可能去唤醒 mo.wait()等待的线程。简单的说就是不同对象的notify()和wait()方法不能互相通信。
分享到:
评论

相关推荐

    北大Java语言程序设计(ppt课件)

    &lt;br&gt; &lt;br&gt;第五讲 输入/输出处理&lt;br&gt; &lt;br&gt;第六讲 例外处理(Exception)&lt;br&gt; &lt;br&gt;第七讲 多线程 &lt;br&gt; &lt;br&gt;第八讲 图形用户界面与事件处理&lt;br&gt; &lt;br&gt;第九讲 Java Applet&lt;br&gt; &lt;br&gt;第十讲 网络通信 &lt;br&gt; &lt;br&gt;第十一讲 J2EE...

    Java案例开发锦集

    目录&lt;br&gt;第一章 Java与Applet&lt;br&gt; 案例一 图形按钮&lt;br&gt; 案例二 模拟工具条&lt;br&gt; 案例三 Applet与Applet在页内的通信&lt;br&gt; 案例四 电子相册&lt;br&gt; 案例五 百页窗效果&lt;br&gt; 案例六 波浪彩虹文字&lt;br&gt; 案例七 3D立体渐层文字...

    JSP訳文--工具--Java

    ASPer看过来&lt;br&gt;困扰JSP的一些问题:jsp和宏之间的争议&lt;br&gt;jsp的5个不足之处&lt;br&gt;JSP不能代替Servlet&lt;br&gt;Resin中的JSP范例&lt;br&gt;JSP发送邮件&lt;br&gt;jsp如何与ejb通信&lt;br&gt;Servlet和JSP的通信&lt;br&gt;jsp与applet通信&lt;br&gt;在JSP中...

    Java JDK实例宝典

    &lt;br&gt;第1章 Java基础 &lt;br&gt;1.1 转换基本数据类型 &lt;br&gt;1.2 Java的运算符 &lt;br&gt;1.3 控制程序的流程 &lt;br&gt;1.4 计算阶乘 &lt;br&gt;1.5 实现命令行程序 &lt;br&gt;第2章 Java面向对象程序设计 &lt;br&gt;2. 1 复数类 &lt;br&gt;2. 2 equals.chashCode...

    水木清华站∶Java版精华区 含jsp及js等集合.chm

    Java版精华区 &lt;br&gt;含java jsp及js等精华帖子合集&lt;br&gt;适合收藏 查询&lt;br&gt;&lt;br&gt;序号 精华区主题 &lt;br&gt;--------------------------------&lt;br&gt; 1. [目录]Java教程 &lt;br&gt; 1. [目录]Java语言教程 &lt;br&gt; 2. [目录]来自java的传说...

    线程间通信

    &lt;br&gt; }&lt;br&gt;}&lt;br&gt;&lt;br&gt;/*&lt;br&gt; 运行结果:&lt;br&gt;张孝祥--&gt;男&lt;br&gt;陈琼--&gt;女&lt;br&gt;张孝祥--&gt;男&lt;br&gt;陈琼--&gt;女&lt;br&gt;张孝祥--&gt;男&lt;br&gt;陈琼--&gt;女&lt;br&gt;张孝祥--&gt;男&lt;br&gt; &lt;br&gt; 可以看出:写入一次,就读取一次.&lt;br&gt; * */&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br...

    java应用软件程序设计

    ReadTestquestion&lt;br&gt;7.5. 课程设计作业&lt;br&gt;第8章 日历记事本&lt;br&gt;8.1. 设计内容&lt;br&gt;8.2. 设计要求&lt;br&gt;8.3. 总体设计&lt;br&gt;8.4. 具体设计&lt;br&gt;8.4.1. 运行效果与程序发布&lt;br&gt;8.4.2. 主类CalendarPad&lt;br&gt;8.4.3. 记事本...

    《Visual.C#.编程精彩百例》配套光盘.part2

    第1篇 Visual C#基础编程实例 &lt;br&gt;实例1 C#经典程序--Hello World &lt;br&gt;实例2 C#的简单输入输出(I/O) &lt;br&gt;实例3 C#的复杂输入输出(I/O) &lt;br&gt;实例4 通信录管理与维护 &lt;br&gt;实例5 文件与目录管理 &lt;br&gt;实例6 用户界面...

    《Visual.C#.编程精彩百例》配套光盘part1

    第1篇 Visual C#基础编程实例 &lt;br&gt;实例1 C#经典程序--Hello World &lt;br&gt;实例2 C#的简单输入输出(I/O) &lt;br&gt;实例3 C#的复杂输入输出(I/O) &lt;br&gt;实例4 通信录管理与维护 &lt;br&gt;实例5 文件与目录管理 &lt;br&gt;实例6 用户界面...

    Linux环境数据库管理员指南

    DB2 173&lt;br&gt;6.3.1 进行安装 174&lt;br&gt;6.3.2 检验安装 180&lt;br&gt;6.4 配置Control Center 182&lt;br&gt;6.5 安装DB2客户机 184&lt;br&gt;6.6 配置DB2客户机与DB2服务器通信 188&lt;br&gt;6.7 小结 194&lt;br&gt;6.8 常见问答 195&lt;br&gt;第7章 在Linux...

    mysql5.1中文手册

    目录&lt;br&gt;&lt;br&gt;前言&lt;br&gt;1. 一般信息&lt;br&gt;1.1. 关于本手册&lt;br&gt;1.2. 本手册采用的惯例&lt;br&gt;1.3. MySQL AB概述&lt;br&gt;1.4. MySQL数据库管理系统概述&lt;br&gt;1.4.1. MySQL的历史&lt;br&gt;1.4.2. MySQL的的主要特性&lt;br&gt;1.4.3. MySQL稳定性...

    java多线程通信图解

    java 多线程 其实就是每个线程都拥有自己的内存空间,多线程之间的通信,比例A线程修改了主内存(main方法的线程)变量,需要把A线程修改的结果同步到主线程中,这时B线程再从主线程获取该变量的值,这样就实现了...

    Java 线程通信示例 源代码

    Java 线程通信示例 源代码 多线程之间通信,值得收藏

    C++网络服务开发套件0.5.5

    通讯&lt;br&gt; 基于XML文本通信协议,客户端可以方便应用于各种环境平台和硬件平台,如Windows、Linux,PDA等开发应用环境中。&lt;br&gt; 完善的通讯协议, 通讯协议跟传输层无关, 目前CWSS支持TCP, UDP和HTTP(POST)三种传输...

    C++网络服务开发套件0.5.6

    通讯&lt;br&gt;基于XML文本通信协议,客户端可以方便应用于各种环境平台和硬件平台,如Windows、Linux,PDA等开发应用环境中。&lt;br&gt;完善的通讯协议, 通讯协议跟传输层无关, 目前CWSS支持TCP, UDP和HTTP(POST)三种传输访问;...

    C++网络服务开发套件0.5.3

    通讯&lt;br&gt; 基于XML文本通信协议,客户端可以方便应用于各种环境平台和硬件平台,如Windows、Linux,PDA等开发应用环境中。&lt;br&gt; 完善的通讯协议, 通讯协议跟传输层无关, 目前CWSS支持TCP, UDP和HTTP(POST)三种传输...

    JAVA线程简介(多线程)

    本教程研究了线程的基础知识 — 线程是什么、线程为什么有用以及怎么开始编写... &lt;br&gt;&lt;br&gt;我们还将研究更复杂的、使用线程的应用程序的基本构件 — 如何在线程之间交换数据、如何控制线程以及线程如何互相通信。 &lt;br&gt;

    java模拟数据库事务

    用java来模拟事务间的并发处理&lt;br&gt;后台是用文件存储来模拟数据库数据&lt;br&gt;用到的技术有:&lt;br&gt;1) java Socket通信&lt;br&gt;2) java多线程缓冲&lt;br&gt;3) 各重java设计模式&lt;br&gt;

    Java 线程间通信,生产者与消费者模型

    使用wait()和notify()实现的生产者与消费者模型,可以了解如何使用wait()和notify()进行线程间通信。(上一次上传的代码有一个问题没有考虑到,这次修补了——CSDN没法撤销资源,只能再上传了)

    超爽的自学课件(java)

    &lt;br&gt;&lt;br&gt;(14) 第14章:多线程&lt;br&gt;Java提供了一套内建的机制,可提供对多个并发子任务的支持,我们称其为“线程”。这线程均在单一的程序内运行。除非机器安装了多个处理器,否则这就是多个子任务的唯一运行方式。...

Global site tag (gtag.js) - Google Analytics