黑马程序员_Java基础[29]_线程间通讯、解决问题、lock

来源:互联网 发布:手机淘宝首页免费模板 编辑:程序博客网 时间:2024/06/01 08:48
---------- android培训 、java培训、期待与您交流! ----------


/*
 * 线程间通讯:-解决安全问题
 * 其实就是多个线程在操作同一个资源
 * 但是操作的动作不同

 */
/*【用举例的思路注解】
 * 【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
0 0
原创粉丝点击