/*
* 线程间通讯:-解决安全问题
* 其实就是多个线程在操作同一个资源
* 但是操作的动作不同
*/
/*【用举例的思路注解】
* 【1】编写完毕,
* 【2】运行我们发现,小焕焕的性别一会女一会man, 是线程出现了安全漏洞
* 接下来,我们封堵上这个漏洞。采用同步
* 想到2个前提,
* 同步的前提
* 1、必须有2个以上的线程 【a】【b】
* 2、必须是一个锁
* 我们先用的是obj 发现不是同一个,然后用了this 也不是,那么该程序在内存总有一个是唯一的
* 发现,内存里有4个类,类名.class 然后我们继续看,这个程序里,还有一个对象是唯一的
* 那就是主函数中的【r】。
* 【3】搞定以后,我们发现,按道理应该是存一个打印一个才对。
* 【等待唤醒机制】 wait();等待 notify();唤醒 notifyAll();全部唤醒 都必须有监视器,就是锁
*
* 这三个方法,都使用在同步中,因为要持有监视器(锁)的线程操作,
* 所以要使用在同步中,因为只有同步才具有监视器(锁)的感念
*
* 为什么这些操作线程的方法要定义在Object类中呢?
* 因为这些 方法在操作同步中线程时,都必须要表示他们所操作线程持有的锁
* 只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒
* 不可以对不同锁中的线程进行唤醒
*
* 也就是说:等待和唤醒必须是同一个锁
*
* 而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object中
*/
//设计一个煤矿堆
class Res{
String name;
String set;
boolean falg = false;
}
//设计一个进货的货车
class Input implements Runnable{
private Res r;
Input(Res r){
this.r=r;
}
Object obj=new Object();
public void run(){
int x=0;
while(true){
synchronized(r){//【a】
if(r.falg)
try{r.wait();}
catch(Exception e){}
if(x==0){
r.name="Yunyao";
r.set="man";
}
else{
r.name="小焕焕";
r.set="女";
}
x=(x+1)%2;
r.falg=true;
r.notify();
}
}
}
}
//设计一个拉货的货车
class Output implements Runnable{
private Res r;
Output(Res r){
this.r=r;
}
Object obj=new Object();
public void run(){
//int x=0;
while(true){
synchronized(r){//【b】
if(!r.falg)
try{r.wait();}catch(Exception e){}
System.out.println(r.name+"..."+r.set+"...");
//x+=1;
r.falg=false;
r.notify();
}
}
}
}
public class D_Th_InputOutpt {
public static void main(String[] args) {
Res r=new Res();//创建一个煤矿堆 程序中唯一的一个对象。
Input in = new Input(r); //创建一个进货的车
Output ot = new Output(r);//创建一个出货的车
Thread t1 = new Thread(in);//进入高速通道
Thread t2 = new Thread(ot);
t1.start();// 开始跑起走
t2.start();
}
}
--------------------------------------------------------------------------------------------------------
优化一
package _Day12;
/*
* 对前一个问题进行优化。
*/
//设计一个煤矿堆
class Res1{
private String name;
private String set;
boolean falg = false;
//同步函数 非静态同步函数 用的锁是 this ,记住了。
public synchronized void setInfo(String name,String set){
if(falg)
try{this.wait();}catch(Exception e){}
this.name=name;
this.set=set;
this.falg=true;
this.notify();
}
public synchronized void showInfo(){
if(!falg)
try{this.wait();}catch(Exception e){}
System.out.println(this.name+"..."+this.set);
this.falg=false;
this.notify();
}
}
//设计一个进货的货车
class Input1 implements Runnable{
private Res1 r;
Input1(Res1 r){
this.r=r;
}
public void run(){
int x=0;
while(true){
if(x==0)
r.setInfo("fei", "man");
else
r.setInfo("小焕焕", "女女女女女");
x=(x+1)%2;
}
}
}
//设计一个拉货的货车
class Output1 implements Runnable{
private Res1 r;
Output1(Res1 r){
this.r=r;
}
public void run(){
while(true){
r.showInfo();
}
}
}
public class D_Th_YouhuaInOut {
public static void main(String[] args) {
Res1 r=new Res1();//创建一个煤矿堆
new Thread(new Input1(r)).start();
new Thread(new Output1(r)).start();
/* 六句优化成上面两句【 匿名对象形式】
Input1 in = new Input1(r); //创建一个进货的车
Output1 ot = new Output1(r);//创建一个出货的车
Thread t1 = new Thread(in);//进入高速通道
Thread t2 = new Thread(ot);
t1.start();// 开始跑起走
t2.start();
*/
}
}
---------------------------------------------------------------------------------------------
/*
* 线程间通信--生产者消费者
*/
/*当生产和消费是单线程的时候没有问题,下面我们把两条线都加一倍试试
发现有问题,经判断是因为线程被唤醒后没有对falg再次进行判断,
因为if只执行一次,现在,我们把if替换成while试试
发现4个线程出现了同时等待。。。。
notify唤醒的是线程池中第一个被等待的线程,很有可能就是本方的,
导致所有线程等待,从而数据错乱
而使用while 则容易出现线程全部出现同时等待的现象。
所以必须使用:notifyAll 全部唤醒
因为有while,所以都会循环去判断标记,进入循环渐进的生成消费。
【自我总结】【注意:1.5以前版本使用】升级1.5里程碑版本的时候改
成了5.0具体【【【LOCK】】】优化synchronized 请看D_Th_Lock
当有多条线程时候,必须要使用while,notifyAll
while 必须去判断标记,是不是在标记允许范围内做动作
notifyAll 要把对方唤醒,
*/
public class D_Th_YouhuaInOut2 {
public static void main(String []args){
Resource r=new Resource();
new Thread(new Shengc(r)).start();
new Thread(new Shengc(r)).start();
new Thread(new Xiaof(r)).start();
new Thread(new Xiaof(r)).start();
Shengc sc=new Shengc(r);
Xiaof xf=new Xiaof(r);
/*
Thread t1=new Thread(sc);
Thread t2=new Thread(xf);
Thread t3=new Thread(sc);
Thread t4=new Thread(xf);
t1.start();
t2.start();
t3.start();
t4.start();
*/
}
}
class Resource{
private String name;
private int count=1;
private boolean falg=false;
public synchronized void set(String name){
while(falg)
try{this.wait();}catch(Exception e){}
this.name=name+"..."+count++;
System.out.println(Thread.currentThread().getName()+"..生产.."+this.name);
this.falg=true;
this.notifyAll();
}
public synchronized void get(){
while(!falg)
try{this.wait();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"-----消费----"+this.name);
this.falg=false;
this.notifyAll();
}
}
class Shengc implements Runnable{
private Resource r;
Shengc(Resource r){
this.r=r;
}
public void run(){
int x=0;
while(true){
r.set("+商品+");
}
}
}
class Xiaof implements Runnable{
private Resource r;
Xiaof(Resource r){
this.r=r;
}
public void run(){
while(true){
r.get();//r.outInfo();
}
}
}
/*
public synchronized void setInfo(String name){
if(falg)
try{this.wait();}catch(Exception e){}
this.name=name+"..."+count++;
this.falg=true;
this.notify();
}
public synchronized void outInfo(){
if(!falg)
try{this.wait();}catch(Exception e){}
System.out.println(this.name);
this.falg=false;
this.notify();
}
*/
/*
if(x==0)
r.setInfo("脉动");
else
r.setInfo("哇哈哈");
x=(x+1)%2;
*/
---------- android培训、 java培训 、期待与您交流!----------
黑马官网: http://edu.csdn.net/heima