<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java學習

    java,spring,structs,hibernate,jsf,ireport,jfreechart,jasperreport,tomcat,jboss -----本博客已經搬家了,新的地址是 http://www.javaly.cn 如果有對文章有任何疑問或者有任何不懂的地方,歡迎到www.javaly.cn (Java樂園)指出,我會盡力幫助解決。一起進步

     

    多線程問題及處理1

    12.4 多線程問題及處理

             多線程編程為程序開發帶來了很多的方便,但是也帶來了一些問題,這些問題是在程序開發過程中必須進行處理的問題。

             這些問題的核心是,如果多個線程同時訪問一個資源,例如變量、文件等,時如何保證訪問安全的問題。在多線程編程中,這種會被多個線程同時訪問的資源叫做臨界資源。

             下面通過一個簡單的示例,演示多個線程訪問臨界資源時產生的問題。在該示例中,啟動了兩個線程類DataThread的對象,該線程每隔200毫秒輸出一次變量n的值,并將n的值減少1。變量n的值存儲在模擬臨界資源的Data類中,該示例的核心是兩個線程類都使用同一個Data類的對象,這樣Data類的這個對象就是一個臨界資源了。示例代碼如下:

                       package syn1;

    /**

     * 模擬臨界資源的類

     */

    public class Data {

             public int n;

             public Data(){

                       n = 60;

             }

    }

    package syn1;

    /**

     * 測試多線程訪問時的問題

     */

    public class TestMulThread1 {

             public static void main(String[] args) {

                       Data data = new Data();

                       DataThread d1 = new DataThread(data,"線程1");

                       DataThread d2 = new DataThread(data,"線程2");

             }

    }

    package syn1;

    /**

     * 訪問數據的線程

     */

    public class DataThread extends Thread {

             Data data;

             String name;

             public DataThread(Data data,String name){

                       this.data = data;

                       this.name = name;

                       start();

             }

              

             public void run(){

                       try{

                                for(int i = 0;i < 10;i++){

                                         System.out.println(name + ":" + data.n);

                                         data.n--;

                                         Thread.sleep(200);

                                }

                       }catch(Exception e){}

             }

    }

             在運行時,因為不同情況下該程序的運行結果會出現不同,該程序的一種執行結果為:

                       線程1:60

    線程2:60

    線程2:58

    線程1:58

    線程2:56

    線程1:56

    線程2:54

    線程1:54

    線程2:52

    線程1:52

    線程2:50

    線程1:50

    線程2:48

    線程1:48

    線程2:47

    線程1:46

    線程2:44

    線程1:44

    線程2:42

    線程1:42

             從執行結果來看,第一次都輸出60是可以理解的,因為線程在執行時首先輸出變量的值,這個時候變量n的值還是初始值60,而后續的輸出就比較麻煩了,在開始的時候兩個變量保持一致的輸出,而不是依次輸出n的每個值的內容,而到將要結束時,線程2輸出47這個中間數值。

             出現這種結果的原因很簡單:線程1改變了變量n的值以后,還沒有來得及輸出,這個變量n的值就被線程2給改變了,所以在輸出時看的輸出都是跳躍的,偶爾出現了連續。

             出現這個問題也比較容易接受,因為最基本的多線程程序,系統只保證線程同時執行,至于哪個先執行,哪個后執行,或者執行中會出現一個線程執行到一半,就把CPU的執行權交給了另外一個線程,這樣線程的執行順序是隨機的,不受控制的。所以會出現上面的結果。

             這種結果在很多實際應用中是不能被接受的,例如銀行的應用,兩個人同時取一個賬戶的存款,一個使用存折、一個使用卡,這樣訪問賬戶的金額就會出現問題。或者是售票系統中,如果也這樣就出現有人買到相同座位的票,而有些座位的票卻未售出。

             在多線程編程中,這個是一個典型的臨界資源問題,解決這個問題最基本,最簡單的思路就是使用同步關鍵字synchronized

             synchronized關鍵字是一個修飾符,可以修飾方法或代碼塊,其的作用就是,對于同一個對象(不是一個類的不同對象), 當多個線程都同時調用該方法或代碼塊時,必須依次執行,也就是說,如果兩個或兩個以上的線程同時執行該段代碼時,如果一個線程已經開始執行該段代碼,則另 外一個線程必須等待這個線程執行完這段代碼才能開始執行。就和在銀行的柜臺辦理業務一樣,營業員就是這個對象,每個顧客就好比線程,當一個顧客開始辦理 時,其它顧客都必須等待,及時這個正在辦理的顧客在辦理過程中接了一個電話 (類比于這個線程釋放了占用CPU的時間,而處于阻塞狀態),其它線程也只能等待。

             使用synchronized關鍵字修改以后的上面的代碼為:

                       package syn2;

    /**

     * 模擬臨界資源的類

     */

    public class Data2 {

             public int n;

             public Data2(){

                       n = 60;

             }

            

             public synchronized void action(String name){

                       System.out.println(name + ":" + n);

                       n--;

             }

    }

    package syn2;

    /**

     * 測試多線程訪問時的問題

     */

    public class TestMulThread2 {

             public static void main(String[] args) {

                       Data2 data = new Data2();

                       Data2Thread d1 = new Data2Thread(data,"線程1");

                       Data2Thread d2 = new Data2Thread(data,"線程2");

             }

    }

    package syn2;

    /**

     * 訪問數據的線程

     */

    public class Data2Thread extends Thread {

             Data2 data;

             String name;

             public Data2Thread(Data2 data,String name){

                       this.data = data;

                       this.name = name;

                       start();

             }

              

             public void run(){

                       try{

                                for(int i = 0;i < 10;i++){

                                         data.action(name);

                                         Thread.sleep(200);

                                }

                       }catch(Exception e){}

             }

    }

             該示例代碼的執行結果會出現不同,一種執行結果為:

                       線程1:60

    線程2:59

    線程2:58

    線程1:57

    線程2:56

    線程1:55

    線程2:54

    線程1:53

    線程2:52

    線程1:51

    線程2:50

    線程1:49

    線程1:48

    線程2:47

    線程2:46

    線程1:45

    線程2:44

    線程1:43

    線程2:42

    線程1:41

             在該示例中,將打印變量n的代碼和變量n變化的代碼組成一個專門的方法action,并且使用修飾符synchronized修改該方法,也就是說對于一個Data2的對象,無論多少個線程同時調用action方法時,只有一個線程完全執行完該方法以后,別的線程才能夠執行該方法。這就相當于一個線程執行到該對象的synchronized方法時,就為這個對象加上了一把鎖,鎖住了這個對象,別的線程在調用該方法時,發現了這把鎖以后就繼續等待下去了。




    (轉)http://blog.csdn.net/Mailbomb/archive/2009/05/23/4210889.aspx

    posted on 2009-06-15 13:24 找個美女做老婆 閱讀(201) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    導航

    統計

    公告

    本blog已經搬到新家了, 新家:www.javaly.cn
     http://www.javaly.cn

    常用鏈接

    留言簿(6)

    隨筆檔案

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 好爽又高潮了毛片免费下载| 久久精品免费观看| 免费在线观看的网站| 亚洲美女免费视频| 日韩免费观看一区| 亚洲精品午夜国产VA久久成人| 免费一级毛suv好看的国产网站| 男人的好免费观看在线视频| 亚洲一区二区三区精品视频| 最近新韩国日本免费观看| 久久亚洲AV成人无码国产| 日韩电影免费观看| 久久亚洲伊人中字综合精品| 久久久精品午夜免费不卡| 亚洲精品国产成人专区| 99re免费在线视频| 久久精品亚洲AV久久久无码 | 国产成人免费ā片在线观看老同学| 国产av无码专区亚洲国产精品| a在线视频免费观看在线视频三区 a毛片成人免费全部播放 | tom影院亚洲国产一区二区| 一个人免费高清在线观看| 亚洲日本一线产区和二线产区对比| 成人奭片免费观看| 国产精品亚洲精品日韩动图 | 曰批全过程免费视频在线观看无码| 久久精品亚洲综合| 在线观看特色大片免费视频| 久久精品国产亚洲AV天海翼| 亚洲乱码中文字幕久久孕妇黑人| 日韩免费电影网站| 亚洲一区二区三区丝袜| 亚洲国产精品成人久久蜜臀 | 亚洲高清一区二区三区| 亚洲?V乱码久久精品蜜桃| 两个人看的www免费高清 | 亚洲国产一区二区视频网站| 精品免费tv久久久久久久| 亚洲香蕉在线观看| 国产亚洲自拍一区| 99在线视频免费观看视频 |