程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 多線程第二彈,多線程

多線程第二彈,多線程

編輯:JAVA綜合教程

多線程第二彈,多線程


  各位看官,抓緊上車,老司機要接著飙車了。

     <!------------------------------我是萬惡的分割線----------------------------------->

  上回咱們講到多線程中有個不得不提的關鍵字---synchronized,不知道各位看官中有沒有對這句話表示費解的(沒有的話,咱們就委屈一下,假裝有),java的關鍵字有很多,多線程的關鍵字也不少,那為什麼會說synchronized是多線程中不得不提的關鍵字呢?各位看官不要著急,備好瓜子,且聽我細細道來。

  話說當年java初現,天地法則新立,各種不足(ps:有不足就對了,沒有漏洞的話那還讓人活不活了),宇宙間那家伙是一片混亂。因為制度的不完善,導致各種行為得不到約束,java這位新君麾下的多線程,I/O等大將更是桀骜不馴,放縱手下無法無天,,,,啥,你問有多瘋狂?據說當初多線程的這個“多”代表2個以上的數時,效率低就不說了,各個線程的數據傳輸也會極其混亂,我嚴重懷疑牛頭馬面就是早期多線程的“傑出作品”。就在這人神共憤的關鍵時刻,天空一聲巨響,synchronized這個小將化好了妝,踏著七彩祥雲就登上了歷史的舞台。

  上回分解時,不知各位看官還有印象沒有,我說過synchronized的作用相當於一個督察,在它的監督下,所有的線程,沒錯,是所有的,都必須按照先後順序一個個來,,,,啥?你媳婦要生了?你要回去看兒子?那你也得排隊,還有,不准有性別歧視,女孩你就不看了?,,,,,啥?你隔壁的二狗的第三只狗一窩生了40只狗,你要去道喜?那你也得排隊

不過,規矩是死的,人是活的,不讓插隊,那多排幾隊,大家同時進行。(ps:腦補一下,驚堂木一聲驚堂),正主來了,今天小子就給大家說道說道synchronized的同步方法(敲黑板)

  上回說到線程安全分為“線程安全”和“非線程安全”,我這有一個祖傳的傳男不傳女,傳內不傳外的秘密,偷偷告訴大家,大家別往外傳,“非線程安全”問題存在於“實例變量”中,如果是方法內的私有變量,則不存在“非線程安全”,也就是俗說的業內黑話---“線程安全”了;如果多個線程同時訪問1個對象中的實例變量,那就有可能出現“非線程安全”問題,此外,如果多線程訪問的對象中如果有多個實例變量,則運行的結果又可能出現交叉的情況,我嚴重懷疑牛頭馬面就是這麼出來的(ps:純屬逗樂,都別當真哈)。

實例如下(如果巧合,看來成功的路都是一樣的,:)):

首先,創建一個HasSelfPrivateNum類

 

 1 public class HasSelfPrivateNum 
 2 {
 3     public void addI(String userName)
 4     {
 5         try
 6         {
 7             int num = 0;
 8             if(userName.equals("a"))
 9             {
10                 num = 100;
11                 System.out.println("a set over");
12                 Thread.sleep(100);
13             }
14             else
15             {
16                 num = 200;
17                 System.out.println("b set over");
18             }
19             System.out.println(userName+" num="+num);
20         }
21         catch(InterruptedException e)
22         {
23             e.printStackTrace();
24         }
25     }
26 }

 

 

 

 

 

創建一個ThreadA類:

 1 public class ThreadA extends Thread 
 2 {
 3     private HasSelfPrivateNum numRef;
 4     public ThreadA(HasSelfPrivateNum numRef)
 5     {
 6         super();
 7         this.numRef=numRef;
 8     }
 9     public void run()
10     {
11         super.run();
12         numRef.addI("a");
13     }
14 }

 

創建一個ThreadB類:

public class ThreadB extends Thread
{
    private HasSelfPrivateNum numRef;
    public ThreadB(HasSelfPrivateNum numRef)
    {
        super();
        this.numRef=numRef;
    }
    public void run()
    {
        super.run();
        numRef.addI("b");
    }
}

下面是Run類:

 1 public class Run 
 2 {
 3     public static void main(String[] args) 
 4     {
 5         HasSelfPrivateNum numRef = new HasSelfPrivateNum();
 6         ThreadA n = new ThreadA(numRef);
 7         n.start();
 8         ThreadB m = new ThreadB(numRef);
 9         m.start();
10     }
11 }

好了,咱們跑一下試試:

試驗結果很明顯,由於沒用synchronized,即兩個線程訪問一個沒有同步的方法,出現了”非線程安全“。下面,我們對程序做一個個微整形,在HasSelfPrivateNum類的public void addI(String userName)方法前添加關鍵字--synchronized,

 1 public class HasSelfPrivateNum 
 2 {
 3     synchronized public void addI(String userName)
 4     {
 5         try
 6         {
 7             int num = 0;
 8             if(userName.equals("a"))
 9             {
10                 num = 100;
11                 System.out.println("a set over");
12                 Thread.sleep(100);
13             }
14             else
15             {
16                 num = 200;
17                 System.out.println("b set over");
18             }
19             System.out.println(userName+" num="+num);
20         }
21         catch(InterruptedException e)
22         {
23             e.printStackTrace();
24         }
25     }
26 }

我們再跑一次:

這次試驗我們可以看出,由於是同步訪問,所以結果是先打印a,然後打印出b.

結論:在兩個線程訪問同一個對象中的同步方法時,一定是線程安全的。

<!---------------------我是萬惡的分割線,我又來了------------->

啪,精彩不斷,好戲連連,預知後事如何,且聽下回分解。

啪,未完待續。

啪,明天見。

 

  

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved