1. 程式人生 > >多線程進階之等待喚醒機制

多線程進階之等待喚醒機制

err read spa zed bject vat stat 算法 pre

/*
 * 線程間通訊實例
 * 多個線程在處理同一資源,但是任務不同
 */

//資源
class Resource
{
    String name;
    String sex;
}
//輸入
class Input implements Runnable
{   
    Resource r;//類對象
    public Input(Resource r)//類對象做構造參數-->初始化資源
    {
        this.r=r;
    }
    public void run()
    {
        int x=0;
        while(true)
        {   
            
/* * 加上同步鎖,因為輸入輸出任務共享資源,所以將資源對象r作為鎖 * 也是為了讓輸入輸出處於同一同步鎖中,這樣輸入就不會在輸入姓名林玲還沒有賦值完性別女 * 時(周俊明被林玲覆蓋),切換執行權 */ synchronized(r) { if(x==0) { r.name="周俊明"; r.sex="男"; }
else { r.name="林玲"; r.sex="女"; } } x=(x+1)%2;//算法切換:不斷由if和else切換 } } } //輸出 class Output implements Runnable { Resource r; public Output(Resource r) { this.r=r; }
public void run() { while(true) { synchronized(r) { System.out.println(r.name+"....."+r.sex); } } } } public class ResourceDemo { 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(); } }

變身 :

/**
 * 等待/喚醒機制
 * 
 * 涉及的方法:
 * 
 * 1.wait():讓線程處於凍結狀態,被wait的線程會被存儲到線程池中.
 * 2.notify():喚醒線程池中的一個線程(任意)
 * 3.notifyAll():喚醒線程池中的索引線程.
 * 
 * 這些方法都必須定義在同步中
 * 因為這些方法是用於操作線程狀態的方法
 * 必須要明確到底操作的是哪個鎖上的線程
 * 
 * 為什麽操作線程的方法wait notify notifyAll定義在Object類中
 * 
 * 因為這些方法是監視器的方法.監視器就是鎖
 * 鎖可以是任意的對象,任意的對象調用的方式一定定義在object類中
 *  */
//資源
class Resour
{
    String name;
    String sex;
    boolean flag=false;//標記
}
//輸入
class Inputs implements Runnable
{   
    Resour r;//類對象
    public Inputs(Resour r)//類對象做構造參數-->初始化資源
    {
        this.r=r;
    }
    public void run()
    {
        int x=0;
        while(true)
        {   
            /*
             * 加上同步鎖,因為輸入輸出任務共享資源,所以將資源對象r作為鎖
             * 也是為了讓輸入輸出處於同一同步鎖中,這樣輸入就不會在輸入姓名林玲還沒有賦值完性別女
             * 時(周俊明被林玲覆蓋),切換執行權
             */
            synchronized(r) 
            {
                try {
                    if(r.flag)
                        r.wait(); //標明睡眠/喚醒同一鎖上線程
                } catch (InterruptedException e) {
                    // TODO: handle exception
                }
            if(x==0)
              {
                r.name="周俊明";
                r.sex="男";
               }
                else
                {
                    r.name="林玲";
                    r.sex="女";
                }
            r.flag=true;
            r.notify();
            }
            
            x=(x+1)%2;//算法切換:不斷由if和else切換
        }
    }
}
//輸出
class Outputs implements Runnable
{
    Resour r;
    public Outputs(Resour r)
    {
        this.r=r;
    }
    public void run() 
    {
        while(true)
        {
            synchronized(r)
            {
                try {
                    if(!r.flag)
                        r.wait(); 
                } catch (InterruptedException e) {
                    
                }
            System.out.println(r.name+"....."+r.sex);
            r.flag=false;
            r.notify();
            }
        }
    }
}
public class ResourceDemo1 {
public static void main(String[] args) {
    //創建資源
    Resour r=new Resour();
    //創建任務
    Inputs in=new Inputs(r);
    Outputs out=new Outputs(r);
    //創建線程
    Thread t1=new Thread(in);
    Thread t2=new Thread(out); 
    
    t1.start();
    t2.start(); 
}
}

優化:

//資源
class Resours
{
    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 Inputce implements Runnable
{   
    Resours r;//類對象
    public Inputce(Resours r)//類對象做構造參數-->初始化資源
    {
        this.r=r;
    }
    public void run()
    {
        int x=0;
        while(true)
        {   
            /*
             * 加上同步鎖,因為輸入輸出任務共享資源,所以將資源對象r作為鎖
             * 也是為了讓輸入輸出處於同一同步鎖中,這樣輸入就不會在輸入姓名林玲還沒有賦值完性別女
             * 時(周俊明被林玲覆蓋),切換執行權
             */
            if(x==0)
              {
                r.set("周俊明","男");
              }
                else
                {
                    r.set("林玲","女");
                 }
             x=(x+1)%2;//算法切換:不斷由if和else切換
             }            
        }
    }
//輸出
class Outputce implements Runnable
{
    Resours r;
    public Outputce(Resours r)
    {
        this.r=r;
    }
    public void run() 
    {
        while(true)
        {
            r.out();
        }
    }
}
public class ResourceDemo2 {
public static void main(String[] args) {
    //創建資源
    Resours r=new Resours();
    //創建任務
    Inputce in=new Inputce(r);
    Outputce out=new Outputce(r);
    //創建線程
    Thread t1=new Thread(in);
    Thread t2=new Thread(out); 
    
    t1.start();
    t2.start(); 
}
}

一不小心就暴露了真實姓名

多線程進階之等待喚醒機制