一、线程间的通信



实例代码:

需求是:输入一个姓名和性别后,就输出一个姓名和性别

class Resource
{
String name;
String sex ;
}
class Input implements Runnable
{
Resource r;
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized (r)
{
if(x==0)
{
r.name = "BLF";
r.sex = "male";
}
else {
r.name = "妮妮妮妮";
r.sex = "female";
}
x = (++x)%2;
}
}
}
} class Output implements Runnable
{
Resource r;
public Output(Resource r) {
// TODO Auto-generated constructor stub
this.r = r;
}
public void run()
{
while(true)
{
synchronized (r) //输入和输出都是应用同一个锁
{
System.out.println(r.name+"..."+r.sex);
}
}
}
}
public class Main
{
public static void main(String[] args)
{
Resource r = new Resource();//共享同一资源
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}

上述代码尽管攻克了。多线程处理同一资源问题,可是出现了一个问题就是,打印非常多一个人名和性别后再打印还有一个,无法实现交替输出。原因:输入线程获取运行权后,不会运行一次,输入姓名和性别,输入线程还拥有运行权。一直赋值。等到切换到输出运行权后,输出最后输入的姓名和性别。可是输出线程也不会仅仅输出一次,一直输出,所以出现打印非常多同一姓名和性别的问题

二、线程的等待/唤醒机制:

用一个boolean值推断是否有数据,有就不放。没有就放

输入线程运行时推断是否有数据,有。就释放运行权,再释放运行资格,进入冻结状态。输出线程运行。输出后boolean值置为false

Input:
if(flag)//有值
wait();//当前冻结,切换输出线程
flag = true;
notify(); Output:
if(!flag)
wait();
flag = false;//flag置为假。输出完成
notify();//唤醒输入线程

等待/唤醒机制:

方法:

1.wait();//使线程进入冻结状态,CPU释放运行权和运行资格,被wait()的线程会被存储到线程池中
2.notify();//唤醒线程池中的随意的一个线程
3.notifyAll();//唤醒全部线程,使之处于运行状态或暂时堵塞状态,总之,使其具备运行资格

这些方法必须定义在同步中。这些方法是用于操作线程状态的方法,所以必须明白在哪个锁上的线程

(wait()A锁的线程。仅仅能用A锁的notify唤醒A锁的线程。

了解:而wait()等方法是定义在Object类中的。这些方法是监视器的方法。而监视器呢。就能够理解为锁,控制哪个锁所属下的线程,而锁又能够是随意的,而全部的类都是继承于Object类的,所以wait()等类是定义在Object里

下述代码就攻克了上述代码的问题,实现了输入输出线程的交替运行

class Resource extends Object
{
String name;
String sex ;
boolean flag = false;
}
class Input implements Runnable
{
Resource r;
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized (r)
{
if(r.flag)
{
try {
r.wait();
} catch (Exception e) {
// TODO: handle exception
} } if(x==0)
{
r.name = "BLF";
r.sex = "male";
}
else {
r.name = "妮妮妮妮";
r.sex = "female";
}
r.flag = true;
r.notify();
x = (++x)%2;
}
}
}
} class Output implements Runnable
{
Resource r;
public Output(Resource r) {
// TODO Auto-generated constructor stub
this.r = r;
}
public void run()
{ while(true)
{
synchronized (r)
{
if(!r.flag)
{
try {
r.wait();
} catch (Exception e) {
// TODO: handle exception
}
} System.out.println(r.name+"..."+r.sex);
r.flag = false;
r.notify();
}
}
}
}
public class Main
{
public static void main(String[] args)
{ Resource r = new Resource();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}

三:等待唤醒机制代码优化

资源中的成员为了可控,应该为私有的。对外提供方法

所以同步的操作。就在Resource类中运行,应用同步函数

class Resource extends Object
{
private String name;
private String sex ;
private boolean flag = false;
public synchronized void set(String name,String sex)
{
// TODO Auto-generated constructor stub
if(flag)
{
try {
this.wait();
} catch (Exception e) {
// TODO: handle exception }
} this.name = name;
this.sex = sex; flag = true;
this.notify();
}
public synchronized void out()
{
if(!flag)
{
try {
this.wait();
} catch (Exception e) {
// TODO: handle exception
}
System.out.println(name+" : "+sex);
flag = false;
this.notify();
}
}
}
class Input implements Runnable
{
Resource r;
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
if(x==0)
{
r.set("BLF", "male");
}
else
{
r.set("妮妮妮妮", "female");
}
x = (++x)%2; }
}
}
class Output implements Runnable
{
Resource r;
public Output(Resource r) {
// TODO Auto-generated constructor stub
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
public class Main
{
public static void main(String[] args)
{ Resource r = new Resource();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}

JAVA学习第二十六课(多线程(五))- 多线程间的通信问题的更多相关文章

  1. JAVA学习第二十九课(经常使用对象API)- String类

    多线程告一段落,開始经常使用对象API的涉及,背也要背下来!.! 日后开发,遇见最多的对象是文字,也就是字符串 String类 字符串是一个特殊对象 字符串一旦初始化就不能够被改变 一.特点 publ ...

  2. Python学习第二十六课——PyMySql(python 链接数据库)

    Python 链接数据库: 需要先安装pymysql 包 可以设置中安装,也可以pip install pymysql 安装 加载驱动: import pymysql # 需要先安装pymysql 包 ...

  3. 风炫安全WEB安全学习第二十六节课 XSS常见绕过防御技巧

    风炫安全WEB安全学习第二十六节课 XSS常见绕过防御技巧 XSS绕过-过滤-编码 核心思想 后台过滤了特殊字符,比如说

  4. 201671010140. 2016-2017-2 《Java程序设计》java学习第十六周

    java学习第十六周-并发        本周,学习了Java中线程,并发的知识,在老师的带领下,进行了对知识的理解学习,以及对实验的运行讲解,对这一块内容掌握的还可以,在自主编程中,也能够完成.线, ...

  5. NeHe OpenGL教程 第二十六课:反射

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. 风炫安全web安全学习第二十八节课 CSRF攻击原理

    风炫安全web安全学习第二十八节课 CSRF攻击原理 CSRF 简介 跨站请求伪造 (Cross-Site Request Forgery, CSRF),也被称为 One Click Attack 或 ...

  7. 风炫安全WEB安全学习第二十三节课 利用XSS获取COOKIE

    风炫安全WEB安全学习第二十三节课 利用XSS获取COOKIE XSS如何利用 获取COOKIE 我们使用pikachu写的pkxss后台 使用方法: <img src="http:/ ...

  8. 风炫安全WEB安全学习第二十节课 反射型XSS讲解

    风炫安全WEB安全学习第二十节课 反射型XSS讲解 反射性xss演示 原理讲解 如果一个应用程序使用动态页面向用户显示错误消息,就会造成一种常见的XSS漏洞.通常,该页面会使用一个包含消息文本的参数, ...

  9. Java学习第二十四天

    1:多线程(理解) (1)JDK5以后的针对线程的锁定操作和释放操作 Lock锁 (2)死锁问题的描述和代码体现 (3)生产者和消费者多线程体现(线程间通信问题) 以学生作为资源来实现的 资源类:St ...

随机推荐

  1. react native windows 搭建(完整版)

    声明:用windows 搭建的react native只能开发安卓应用 1.准备安装java jdk,以及Android SDK 传送门: java   JDK   Android SDK(自行寻找) ...

  2. 关于C++编译的程序无法在新一台电脑上运行总结

    最近在调用一个SDK调试一个主板的DPIO. 可是编译好的程序在开发电脑上运行没问题,到了新主板建立的电脑系统上就出问题. 总结了下要注意一下几方面. 1:程序本身要没有问题.至少在开发电脑系统环境下 ...

  3. 使用Bind服务配置DNS服务器

    bind是什么 bind是DNS服务器软件 ,他的服务名称是named 功能区分: 正向解析:根据主机名查找对应的IP地址 反向解析:根据IP地址查找对应的主机名(域名) 工作形式上区分: 主服务器: ...

  4. java的maven项目(三)私服的搭建(windows版)

    1       私服 nexus 安装nexus 启动服务 启动失败的解决方法: 登录nexus 用户名/密码  admin/admin123 仓库类型 Virtual   虚拟仓库 Proxy  代 ...

  5. hdu 1411(四面体的体积)

    校庆神秘建筑 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  6. 火狐firefox插件配合scrapy,注意tbody会导致empty

    有2个常有插件,一个是xpath checker,一个是firepath(配合firebug) xpath checker是个好东西,不仅可以分析,还可以验证自己抽取的xpath是否正确 但xpath ...

  7. 数据排序 第二讲( 各种排序方法 结合noi题库1.10)

    先来个题练练手吧! 例题 04:奖学金 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生 ...

  8. vc ini配置文件读写

    ini文件(即Initialization file),这种类型的文件中通常存放的是一个程序的初始化信息.ini文件由若干个节(Section)组成,每个Section由若干键(Key)组成,每个Ke ...

  9. [CF392E]Deleting Substrings

    “unexpected, right?”大概可以翻译成“没想到吧!” 题意:给两个序列$w_{1\cdots n}$和$v_{1\cdots n}$,你可以多次删除$w$的子串$w_{l\cdots ...

  10. [BZOJ2753]滑雪与时间胶囊

    第一问直接把可以走的边连起来bfs一遍即可 第二问可以用类似kruskal的方法,只不过排序的依据应该变为第一关键字为终点高度(从大到小),第二关键字为边权(从小到大),只排序可以走的边 因为同样高度 ...