java-多线程的练习----妖,等待唤醒,代码重构,lock到condition
1 需求
资源有姓名和性别。
两个线程,
一个负责给姓名和性别赋值,
一个负责获取姓名和性别的值。
要求1,运行一下,解决程序的 "妖"的问题。
要求2,实现正确数据的间隔输出 如
张飞--男
rose--女女女
张飞--男
rose--女女女
要求3,对代码进行重构。
将name,sex私有化,资源类提供对其访问的方法。
要求4,将程序改成JDK1.5的Lock Condition接口。
-------------------------------------
2 妖的出现和解决
原代码:
//描述资源。
class Resource
{
String name;
String sex;
}
//赋值线程任务
class Input implements Runnable
{
private Resource r;
// private Object obj = new Object();
Input(Resource r)//任务一初始化就必须有要处理的资源。
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
{
if(x==0)
{
r.name = "张飞";
r.sex = "男";
}
else
{
r.name = "rose";
r.sex = "女女女女";
}
}
x = (x+1)%2;//实现切换。
}
}
}
//获取值线程任务
class Output implements Runnable
{
private Resource r ;
// private Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{ System.out.println(r.name+"....."+r.sex);
}
}
} class ThreadTest2
{
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(); }
}
测试结果: 会出现张飞.....女.或者是rose.....男,

分析原因:假如某个时刻,name=rose,sex=女,进入if中,进行了name=张三后就停止了,不进行了sex的赋值,进入打印,这是时的name=张三,sex=女;
解决方法:出现了安全问题.需要加入同步.详情请点击,
//描述资源。
class Resource
{
String name;
String sex;
}
//赋值线程任务
class Input implements Runnable
{
private Resource r;
// private Object obj = new Object();
Input(Resource r)//任务一初始化就必须有要处理的资源。
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r) //加入同步
{
if(x==0)
{
r.name = "张飞";
r.sex = "男";
}
else
{
r.name = "rose";
r.sex = "女女女女";
}
}
x = (x+1)%2;//实现切换。
}
}
}
//获取值线程任务
class Output implements Runnable
{
private Resource r ;
// private Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r) //加入同步
{
System.out.println(r.name+"....."+r.sex);
}
}
}
} class ThreadTest2
{
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(); }
}
测试结果

-------------------------------------
3 等待唤醒
出现问题:由上面的结果可知,出现了大量的男或女,没有出现一男一女
解决问题:加入等待唤醒.输入后等待,唤醒输出,输出后,唤醒输入;一般要加入个标志
//描述资源。
class Resource
{
String name;
String sex;
//定义标记,
boolean flag = false; }
//赋值线程任务
class Input implements Runnable
{
private Resource r;
// private Object obj = new Object();
Input(Resource r)//任务一初始化就必须有要处理的资源。
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if(r.flag)
try{r.wait();}catch(InterruptedException e){}//等待唤醒机制
if(x==0)
{
r.name = "张飞";
r.sex = "男";
}
else
{
r.name = "rose";
r.sex = "女女女女";
} r.flag = true;
r.notify(); //等待唤醒机制
}
x = (x+1)%2;//实现切换。
}
}
}
//获取值线程任务
class Output implements Runnable
{
private Resource r ;
// private Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
if(!r.flag)//等待唤醒机制
try{r.wait();}catch(InterruptedException e){}
System.out.println(r.name+"....."+r.sex);
r.flag = false;
r.notify();//等待唤醒机制
}
}
}
} class ThreadTest2_2
{
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(); }
}
测试结果

-------------------------------------
4 代码重构
解决问题:将name,sex私有化,资源类提供对其访问的方法。这时加同步要放在共有资源里面
//描述资源。
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){}
this.name = name;
this.sex = sex;
flag = true;
this.notify();
} //获取值。
public synchronized void out()
{
if(!flag)
try{this.wait();}catch(InterruptedException e){}
System.out.println(name+"------"+sex);
flag = false;
this.notify();
} }
//赋值线程任务
class Input implements Runnable
{
private Resource r;
Input(Resource r)//任务一初始化就必须有要处理的资源。
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
if(x==0)
{
r.set("张飞","男");
}
else
{
r.set("rose","女女女女");
}
x = (x+1)%2;//实现切换。
}
}
}
//获取值线程任务
class Output implements Runnable
{
private Resource r ;
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
} class ThreadTest2_3
{
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(); }
}
-------------------------------------
5,将程序改成JDK1.5的Lock Condition接口
解决问题:Lock替换了 同步函数或者同步代码块。Condition替代了 监视器方法,将监视器方法从锁上分离出来,单独封装成Condition对象。
import java.util.concurrent.locks.*;
//描述资源。
class Resource
{
private String name;
private String sex; //程序改成JDK1.5的Lock Condition接口
//定义标记,
private boolean flag = false; //先创建锁对象。
private final Lock lock = new ReentrantLock();// //通过锁对象获取监视器对象。
private Condition con = lock.newCondition();// //赋值功能。
public void set(String name,String sex)
{
lock.lock();//
try{
if(flag)
try{con.await();}catch(InterruptedException e){}//
this.name = name;
this.sex = sex;
flag = true;
con.signal();//
}finally{
lock.unlock();//
}
} //获取值。
public void out()
{
lock.lock();//
try{
if(!flag)
try{con.await();}catch(InterruptedException e){}//
System.out.println(name+"------"+sex);
flag = false;
con.signal();//
}finally{
lock.unlock();//
}
} }
//赋值线程任务
class Input implements Runnable
{
private Resource r;
Input(Resource r)//任务一初始化就必须有要处理的资源。
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
if(x==0)
{
r.set("张飞","男");
}
else
{
r.set("rose","女女女女");
}
x = (x+1)%2;//实现切换。
}
}
}
//获取值线程任务
class Output implements Runnable
{
private Resource r ;
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
} class ThreadTest2_4
{
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-多线程的练习----妖,等待唤醒,代码重构,lock到condition的更多相关文章
- 多线程的练习----妖,等待唤醒,代码重构,lock到condition
× 目录 [1]需求 [2]妖的出现和解决 [3]等待唤醒 [4]代码重构 [5]改成Lock Condition ------------------------------------- 1,需求 ...
- “全栈2019”Java多线程第二十一章:同步代码块产生死锁的例子
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第十八章:同步代码块双重判断详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java生鲜电商平台-一次代码重构的实战案例
Java生鲜电商平台-一次代码重构的实战案例 说明,Java开源生鲜电商平台-一次代码重构的实战案例,根据实际的例子,分析出重构与抽象,使代码更加的健壮与高效. 1.业务说明 系统原先已有登录功能,我 ...
- Java多线程5:线程等待与唤醒
原文:http://www.cnblogs.com/skywang12345/p/3479224.html wait(),notify(), notifyAll()等方法介绍在Object.java中 ...
- Java多线程--让主线程等待子线程执行完毕
使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...
- 多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)
一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. ...
- java多线程 生产者消费者案例-虚假唤醒
package com.java.juc; public class TestProductAndConsumer { public static void main(String[] args) { ...
- java多线程(线程通信-等待换新机制-代码优化)
等待唤醒机制涉及方法: wait():让线程处于冻结状态,被wait的线程会被存储到线程池中. noticfy():唤醒同一个线程池中一个线程(任意也可能是当前wait的线程) notifyAll() ...
随机推荐
- bzoj1913: [Apio2010]signaling 信号覆盖
传送门 题解传送门 //Achen #include<algorithm> #include<iostream> #include<cstring> #includ ...
- .git文件夹太大问题及解决方法
最近我们做了自动化构建, 发现文件.git文件夹越来越大, 求后端小伙伴帮忙, 小伙伴指点了一下说周末弄了一下, 忘记命令的.大致的意思就是找到git 提交了哪些大文件. 然后重构git, 先分享给小 ...
- Hack Tools
Tools 2011-03-17 13:54:36| 分类: Security|举报|字号 订阅 Packet Shaper:Nemesis: a command line packet s ...
- 使用dubbo中间件出现NoSuchBeanDefinitionException异常
dubbo中间件中有一个import com.alibaba.dubbo.config.annotation.Service类,在service层添加注解时要注意,我们添加的是import org.s ...
- 转载https://www.luogu.org/problemnew/solution/P1665,http://bailian.openjudge.cn/practice/2002/的新解法
不知道为什么O(n^4)O(n4)的玄学方法能过,正解显然是O(n^2)O(n2)的,枚举对角线,然后算出另外两点判断存不存在. 关键就在怎么通过对角线算出另外两点的坐标. 先贴公式. int mid ...
- 如何做系列(1)- mybatis 如何实现分页?
第一个做法,就是直接使用我们的sql语句进行分页,也就是在mapper里面加上分页的语句就好了. <select id="" parameterType="&quo ...
- python内置类型详细解释
文章编写借鉴于内置类型 - Python 3.7.3 文档,主要用于自己学习和记录 python主要内置类型包括数字.序列.映射.类.实例和异常 有些多项集类是可变的.它们用于添加.移除或重排其成员的 ...
- [转]在C#代码中应用Log4Net系列教程(附源代码)
Log4Net应该可以说是DotNet中最流行的开源日志组件了.以前需要苦逼写的日志类,在Log4Net中简单地配置一下就搞定了.没用过Log4Net,真心不知道原来日志组件也可以做得这么灵活,当然这 ...
- 【HAOI2015】树上染色—树形dp
[HAOI2015]树上染色 [题目描述]有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色.将所有点染色后,你会获得 ...
- Mysql--数据表碎片优化方法
碎片产生原因: 大量批量插入和删除操作数据库,基于线性表的顺序存储结构的特点,出现了大量的空间碎片.一.优化步骤: 1.查看整库的情况 2.方便优化 3.整库所有表, 包含行数 索引长度 碎片空间 二 ...