線程Demo

/**
* 需求:簡單的賣票程序。
多個窗口同時買票。
思路:多個窗口就是多個線程。
票就是共享的數據,每個線程都有唯一的它
*/

注意:線程終止的時刻是run方法裏的while循環終止的時候。

public class TicketDemo {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //創建共享數據票
        Ticket t=new Ticket(100);
        new SellTicket(t).start();
        new SellTicket(t).start();
        
    }

}
//票
class Ticket 
{
     //初始化票爲100張
    private int i=100;
    public Ticket (int i)
    {
        this.i=i;
    }
    public int getI() {
        return i;
    }

    public  void setI(int i) {
        this.i = i;
    }
}
//買票的線程
class SellTicket  extends Thread
{
    private Ticket t;
    public SellTicket (Ticket t)
    {
        this.t=t;
    }
    @Override
    public  void run() {
        // TODO Auto-generated method stub
        
         
        while(t.getI()>0)
        {
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                // TODO Auto-generated catch block
//                e.printStackTrace();
//          使用同步代碼塊,防止兩個窗口打印無法同步
            synchronized(this.t)
            {
            System.out.println(Thread.currentThread().getName()+"剩餘票數爲"+t.getI());
            t.setI(t.getI()-1);
            }
        }
         
    }
    
}
/**
* 靜態的同步函數使用的鎖是 該函數所屬字節碼文件對象 
可以用 getClass方法獲取,也可以用當前 類名.class 表示即該類。
*/

public class StaticSynFunctionDemo {
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        Tick t=new Tick();
        Thread t1=new Thread (t);
        Thread t2=new Thread(t);
        //t1將會只執行run的同步代碼塊
        t1.start();
        Thread.sleep(1000);
        t.flag=false;
        //t2將只會執行同步方法showTick。
        t2.start();
    }
}
//票:同步代碼塊與靜態方法同步
class Tick  implements Runnable
{
    private static int i=100;
    //一個標誌位,決定由同步方法執行,還是同步代碼塊執行
    boolean flag=true;
    @Override
    public void run() {
        // TODO Auto-generated method stub
        if(flag)
        {
            //拿到flag爲true的線程將在這裏不停的循環
            while(true)
            {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                synchronized (Tick.class)
                {
                System.out.println(Thread.currentThread().getName()+"--run代碼塊--"+i--);
                }
            }
            
        }else
        {
            //拿到flag爲false的線程將不停的在這裏離循環
            while(true)
            {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                showTick();
            }
        }
        
    }
    public static synchronized void showTick ()
    {
        System.out.println(Thread.currentThread().getName()+"--showTick方法--"+i--);
    }
    
}

/**
* 死鎖:常見情景之一:同步的嵌套。即線程x要先拿a,再拿b兩個鎖纔可以執行下去,而線程y剛好相反。

                               剛好x拿了a鎖時,y也拿了b鎖,接下來雙發互強對方線程手上的鎖。
* 總結死鎖原因:一:執行同步時要拿兩個不同的對象鎖 
*                     二:第二個對象鎖被別的線程拿走了,且不還,不釋放
*                           導致拿了第一個對象鎖的線程無法執行下去。
*/

public class DeadLockDemo {
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
       Piao p=new Piao();
       Thread t1=new Thread(p);
       Thread t2=new Thread(p);
       t1.start();
       Thread.sleep(1);
       p.flag=false;
       t2.start();
    }

}
//票
class Piao implements Runnable
{
   private int i=100;
   //用來做同步的鎖
   Object o=new Object();
   //標誌位,不同線程執行不同標誌位下的代碼
   boolean flag=true;
    @Override
    public void run() {
        // TODO Auto-generated method stub
        if(flag)
        {
            while(true)
            {
                //flag爲true的線程在此執行,
                //執行下面的第一件事情是拿到對象o的鎖
               synchronized (o)
               {   
                   
                   //執行下面的第一件事情是拿到該對象鎖piao
                   show();
                }
            }
        }else
        {
            while(true)
            {     
                //flag爲false的線程執行下面show()方法
                //執行show方法的第一個事情是拿到該對象鎖piao.
                this.show();
            }
        }
    }
    public synchronized void show()
    {
        synchronized (o)
        {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-show方法-"+i--);
        }
    }
    
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章