1. 程式人生 > >Thread實現多執行緒、死鎖、同步鎖

Thread實現多執行緒、死鎖、同步鎖

1、實現一個類MyThread繼承Thread並重寫run()方法 啟動執行緒方法:例項化MyThread物件,並呼叫start()方法 多個執行緒之間交替執行(搶時間片) 主執行緒(main方法)有優先執行的許可權,但並不絕對

2、實現一個類MyThread實現Runnable介面下的run()方法 啟動執行緒方法:例項化MyThread物件mt,並將mt作為例項化Thread的引數,再通過Thread物件呼叫start()方法 MyThread mt = new MyThread(); Thread t = new Thread(mt); t.start();

實現點選按鈕,球向前慢慢滾動的效果: public class Test extends JFrame{

    private MyPanel mp;     public static void main(String[] args) {         new Test().setVisible(true);

    }     private JPanel panel;     private JButton btn;     public Test() {         this.setDefaultCloseOperation(EXIT_ON_CLOSE);         panel = new JPanel();         panel.setLayout(new BorderLayout());         setBounds(300, 100, 600, 300);         this.setContentPane(panel);                  mp = new MyPanel();         panel.add(mp);                  btn = new JButton("開始");                  btn.addActionListener(new ActionListener() {                          @Override             public void actionPerformed(ActionEvent e) {                                  Thread t = new Thread(mp);                 t.start();                              }         });         panel.add(btn,BorderLayout.SOUTH);     }          private class MyPanel extends JPanel implements Runnable{

        private int x = 100;         public void paint(Graphics g) {             super.paint(g);             g.fillOval(x, 80, 50, 50);         }         @Override         public void run() {             for (int i = 0; i < 50; i++) {                 x += 5 ;                 try {                     Thread.sleep(150);                 } catch (InterruptedException e) {                     // TODO Auto-generated catch block                     e.printStackTrace();                 }                 repaint();             }                      }     } }

3、使用匿名類,繼承Thread,重寫run()方法,直接在run()方法中寫業務程式碼 匿名類的一個好處是可以很方便的訪問外部的區域性變數 public class TestThread {        public static void main(String[] args) {                    Hero gareen = new Hero();         gareen.name = "蓋倫";         gareen.hp = 616;         gareen.damage = 50;            Hero teemo = new Hero();         teemo.name = "提莫";         teemo.hp = 300;         teemo.damage = 30;                    Hero bh = new Hero();         bh.name = "賞金獵人";         bh.hp = 500;         bh.damage = 65;                    Hero leesin = new Hero();         leesin.name = "盲僧";         leesin.hp = 455;         leesin.damage = 80;                    //匿名類         Thread t1= new Thread(){             public void run(){                 //匿名類中用到外部的區域性變數teemo,必須把teemo宣告為final                 //但是在JDK7以後,就不是必須加final的了                 while(!teemo.isDead()){                     gareen.attackHero(teemo);                 }                           }         };                   t1.start();                    Thread t2= new Thread(){             public void run(){                 while(!leesin.isDead()){                     bh.attackHero(leesin);                 }                           }         };         t2.start();               }        }

注意: 啟動執行緒是start()方法,run()並不能啟動一個新的執行緒

常見執行緒方法:

sleep    當前執行緒暫停 Thread.sleep(1000); 表示當前執行緒暫停1000毫秒 ,其他執行緒不受影響 

join    加入到當前執行緒中 Thread t1= new Thread(){             public void run(){                 while(!teemo.isDead()){                     gareen.attackHero(teemo);                 }             }         }; t1.start(); try {  //main執行緒在執行時,t1執行緒加入到main執行緒中來,只有t1執行緒執行結束,才會繼續往下走       t1.join(); } catch (InterruptedException e) { e.printStackTrace();

}

setPriority    執行緒優先順序 當執行緒處於競爭關係的時候,優先順序高的執行緒會有更大的機率獲得CPU資源  Thread t1 = new Thread(); Thread t2 = new Thread(); t1.setPriority(Thread.MAX_PRIORITY);最大為10 t2.setPriority(Thread.MIN_PRIORITY);最小為0

yield    臨時暫停     當前執行緒,臨時暫停,使得其他執行緒可以有更多的機會佔用CPU資源

setDaemon    守護執行緒 如果一個程序只剩下守護執行緒,那麼程序就會自動結束。

執行緒同步

沒有實現同步 public class Bank {

    public static void main(String[] args) {         new Bank().way();

    }

    public void way() {         Family f = new Family();         Thread t1 = new Thread(f, "丈夫");

        //new Thread(f, "執行緒名稱");         Thread t2 = new Thread(f, "妻子");         t1.start();         t2.start();         try {             Thread.sleep(3000);         } catch (InterruptedException e) {             // TODO Auto-generated catch block             e.printStackTrace();         }         while (true) {             if (f.times >= 2) {                 f.show();                 break;             }         }

    }

    private class Family implements Runnable {         private int totalMoney;         private int getMoney;         private int currentMoney;         private int times = 0;         private Object key = new Object();

        public Family() {             totalMoney = 5000;             getMoney = 2000;             currentMoney = 0;         }

        @Override         public void run() {

            //Thread.currentThread()當前執行緒             System.out.println(Thread.currentThread().getName() + "---取了" + getMoney + "元");             //給取出的錢重新賦值             currentMoney += getMoney;                          //銀行存款剩餘             int tem = totalMoney - getMoney;                          //在銀行存款變換之前,執行緒沉睡1s,這時,時間片被另一個執行緒搶走             try {                 Thread.sleep(1000);             } catch (InterruptedException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }              //給銀行存款重新賦值             totalMoney = tem;             times++;         }                  public void show() {             System.out.println("銀行存款剩餘:" + totalMoney + "\t取出:" + currentMoney);         }     } } 執行: 丈夫---取了2000元 妻子---取了2000元 銀行存款剩餘:3000    取出:4000

新增同步鎖:     方法一:         //物件必須在run()方法體外面         private Object key = new Object();

        public void run() {             //synchronized( 可以是任意物件,例如:this)             synchronized (key) {                 System.out.println(Thread.currentThread().getName() + "---取了" + getMoney + "元");                 currentMoney += getMoney;                 int tem = totalMoney - getMoney;                 try {                     Thread.sleep(1000);                 } catch (InterruptedException e) {                     // TODO Auto-generated catch block                     e.printStackTrace();                 }                 totalMoney = tem;                 times++;             }

        }

    方法二:         public void run() {                          syn();

        }         public synchronized void syn() {             System.out.println(Thread.currentThread().getName() + "---取了" + getMoney + "元");             currentMoney += getMoney;             int tem = totalMoney - getMoney;             try {                 Thread.sleep(1000);             } catch (InterruptedException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }             totalMoney = tem;             times++;         } 執行: 丈夫---取了2000元 妻子---取了2000元 銀行存款剩餘:1000    取出:4000

死鎖

1. 執行緒1 首先佔有物件1,接著試圖佔有物件2 2. 執行緒2 首先佔有物件2,接著試圖佔有物件1 3. 執行緒1 等待執行緒2釋放物件2 4. 與此同時,執行緒2等待執行緒1釋放物件1 就會。。。一直等待下去,直到天荒地老,海枯石爛,山無稜 ,天地合。。。

public class Test04 {

    public static void main(String[] args) {         new Test04();

    }     public Test04() {         MyThread mt = new MyThread();         Thread t1 = new Thread(mt,"A");         Thread t2 = new Thread(mt,"B");         t1.start();t2.start();     }     public class MyThread implements Runnable{         private Object o1 = new Object();         private Object o2 = new Object();         private boolean b = false;         @Override         public void run() {             if(b) {                 b = !b;                 synchronized (o1) {                     System.out.println(Thread.currentThread().getName()+"拿到第一把鑰匙!");                     try {                         Thread.sleep(1000);                     } catch (InterruptedException e) {                         // TODO Auto-generated catch block                         e.printStackTrace();                     }                     synchronized (o2) {                         System.out.println(Thread.currentThread().getName()+"拿到第二把鑰匙!");                     }                 }             }else {                 b = !b;                 synchronized (o2) {                     System.out.println(Thread.currentThread().getName()+"拿到第二把鑰匙!");                     try {                         Thread.sleep(1000);                     } catch (InterruptedException e) {                         // TODO Auto-generated catch block                         e.printStackTrace();                     }                     synchronized (o1) {                         System.out.println(Thread.currentThread().getName()+"拿到第一把鑰匙!");                     }                 }             }                      }              }

} 執行: B拿到第一把鑰匙! A拿到第二把鑰匙! (一直在執行中,程式沒有結束!)