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

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

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

    Dict.CN 在線詞典, 英語學習, 在線翻譯

    都市淘沙者

    荔枝FM Everyone can be host

    統計

    留言簿(23)

    積分與排名

    優秀學習網站

    友情連接

    閱讀排行榜

    評論排行榜

    實戰體會Java的多線程編程 【轉】

     在Java 程序中使用多線程要比在 C 或 C++ 中容易得多,這是因為 Java 編程語言提供了語言級的支持。本文通過簡單的編程示例來說明 Java 程序中的多線程是多么直觀。讀完本文以后,用戶應該能夠編寫簡單的多線程程序。

      為什么會排隊等待?

      下面的這個簡單的 Java 程序完成四項不相關的任務。這樣的程序有單個控制線程,控制在這四個任務之間線性地移動。此外,因為所需的資源 ? 打印機、磁盤、數據庫和顯示屏 -- 由于硬件和軟件的限制都有內在的潛伏時間,所以每項任務都包含明顯的等待時間。因此,程序在訪問數據庫之前必須等待打印機完成打印文件的任務,等等。如果您正在等待程序的完成,則這是對計算資源和您的時間的一種拙劣使用。改進此程序的一種方法是使它成為多線程的。

      四項不相關的任務
    class myclass {
     
    static public void main(String args[]) {
      print_a_file();
      manipulate_another_file();
      access_database();
      draw_picture_on_screen();
     }

    }

     在本例中,每項任務在開始之前必須等待前一項任務完成,即使所涉及的任務毫不相關也是這樣。但是,在現實生活中,我們經常使用多線程模型。我們在處理某些任務的同時也可以讓孩子、配偶和父母完成別的任務。例如,我在寫信的同時可能打發我的兒子去郵局買郵票。用軟件術語來說,這稱為多個控制(或執行)線程。

      可以用兩種不同的方法來獲得多個控制線程:

      多個進程

      在大多數操作系統中都可以創建多個進程。當一個程序啟動時,它可以為即將開始的每項任務創建一個進程,并允許它們同時運行。當一個程序因等待網絡訪問或用戶輸入而被阻塞時,另一個程序還可以運行,這樣就增加了資源利用率。但是,按照這種方式創建每個進程要付出一定的代價:設置一個進程要占用相當一部分處理器時間和內存資源。而且,大多數操作系統不允許進程訪問其他進程的內存空間。因此,進程間的通信很不方便,并且也不會將它自己提供給容易的編程模型。

      線程

      線程也稱為輕型進程 (LWP)。因為線程只能在單個進程的作用域內活動,所以創建線程比創建進程要廉價得多。這樣,因為線程允許協作和數據交換,并且在計算資源方面非常廉價,所以線程比進程更可取。線程需要操作系統的支持,因此不是所有的機器都提供線程。Java 編程語言,作為相當新的一種語言,已將線程支持與語言本身合為一體,這樣就對線程提供了強健的支持。

      使用 Java 編程語言實現線程

      Java編程語言使多線程如此簡單有效,以致于某些程序員說它實際上是自然的。盡管在 Java 中使用線程比在其他語言中要容易得多,仍然有一些概念需要掌握。要記住的一件重要的事情是 main() 函數也是一個線程,并可用來做有用的工作。程序員只有在需要多個線程時才需要創建新的線程。

      Thread 類

      Thread 類是一個具體的類,即不是抽象類,該類封裝了線程的行為。要創建一個線程,程序員必須創建一個從 Thread 類導出的新類。程序員必須覆蓋 Thread 的 run() 函數來完成有用的工作。用戶并不直接調用此函數;而是必須調用 Thread 的 start() 函數,該函數再調用 run()。下面的代碼說明了它的用法:

      創建兩個新線程

    import java.util.*;

    class TimePrinter extends Thread {
     
    int pauseTime;
     String name;
     
    public TimePrinter(int x, String n) {
      pauseTime 
    = x;
      name 
    = n;
     }


     
    public void run() {
      
    while(true{
       
    try {
        System.out.println(name 
    + ":" + new Date(System.currentTimeMillis()));
        Thread.sleep(pauseTime);
       }
     catch(Exception e) {
        System.out.println(e);
       }

      }

     }


     
    static public void main(String args[]) {
      TimePrinter tp1 
    = new TimePrinter(1000"Fast Guy");
      tp1.start();
      TimePrinter tp2 
    = new TimePrinter(3000"Slow Guy");
      tp2.start();
     }

    }

     在本例中,我們可以看到一個簡單的程序,它按兩個不同的時間間隔(1 秒和 3 秒)在屏幕上顯示當前時間。這是通過創建兩個新線程來完成的,包括 main() 共三個線程。但是,因為有時要作為線程運行的類可能已經是某個類層次的一部分,所以就不能再按這種機制創建線程。雖然在同一個類中可以實現任意數量的接口,但 Java 編程語言只允許一個類有一個父類。同時,某些程序員避免從 Thread 類導出,因為它強加了類層次。對于這種情況,就要 runnable 接口。

      Runnable 接口

      此接口只有一個函數,run(),此函數必須由實現了此接口的類實現。但是,就運行這個類而論,其語義與前一個示例稍有不同。我們可以用 runnable 接口改寫前一個示例。(不同的部分用黑體表示。)

      創建兩個新線程而不強加類層次

    import java.util.*;

    class TimePrinter implements Runnable {
     
    int pauseTime;
     String name;
     
    public TimePrinter(int x, String n) {
      pauseTime 
    = x;
      name 
    = n;
     }


     
    public void run() {
      
    while(true{
       
    try {
        System.out.println(name 
    + ":" + new Date(System.currentTimeMillis()));
        Thread.sleep(pauseTime);
       }
     catch(Exception e) {
        System.out.println(e);
       }

      }

     }


     
    static public void main(String args[]) {
      Thread t1 
    = new Thread(new TimePrinter(1000"Fast Guy"));
      t1.start();
      Thread t2 
    = new Thread(new TimePrinter(3000"Slow Guy"));
      t2.start();
     }

    }

      請注意,當使用 runnable 接口時,您不能直接創建所需類的對象并運行它;必須從 Thread 類的一個實例內部運行它。許多程序員更喜歡 runnable 接口,因為從 Thread 類繼承會強加類層次。
    synchronized 關鍵字

      到目前為止,我們看到的示例都只是以非常簡單的方式來利用線程。只有最小的數據流,而且不會出現兩個線程訪問同一個對象的情況。但是,在大多數有用的程序中,線程之間通常有信息流。試考慮一個金融應用程序,它有一個 Account 對象,如下例中所示:

      一個銀行中的多項活動

    public class Account {
     String holderName;
     
    float amount;
     
    public Account(String name, float amt) {
      holderName 
    = name;
      amount 
    = amt;
     }


     
    public void deposit(float amt) {
      amount 
    += amt;
     }


     
    public void withdraw(float amt) {
      amount 
    -= amt;
     }


     
    public float checkBalance() {
      
    return amount;
     }

    }

      在此代碼樣例中潛伏著一個錯誤。如果此類用于單線程應用程序,不會有任何問題。但是,在多線程應用程序的情況中,不同的線程就有可能同時訪問同一個 Account 對象,比如說一個聯合帳戶的所有者在不同的 ATM 上同時進行訪問。在這種情況下,存入和支出就可能以這樣的方式發生:一個事務被另一個事務覆蓋。這種情況將是災難性的。但是,Java 編程語言提供了一種簡單的機制來防止發生這種覆蓋。每個對象在運行時都有一個關聯的鎖。這個鎖可通過為方法添加關鍵字 synchronized 來獲得。這樣,修訂過的 Account 對象(如下所示)將不會遭受像數據損壞這樣的錯誤:

      對一個銀行中的多項活動進行同步處理

    public class Account {
     String holderName;
     
    float amount;
     
    public Account(String name, float amt) {
      holderName 
    = name;
      amount 
    = amt;
     }


     
    public synchronized void deposit(float amt) {
      amount 
    += amt;
     }


     
    public synchronized void withdraw(float amt) {
      amount 
    -= amt;
     }


     
    public float checkBalance() {
      
    return amount;
     }

    }

      deposit() 和 withdraw() 函數都需要這個鎖來進行操作,所以當一個函數運行時,另一個函數就被阻塞。請注意, checkBalance() 未作更改,它嚴格是一個讀函數。因為 checkBalance() 未作同步處理,所以任何其他方法都不會阻塞它,它也不會阻塞任何其他方法,不管那些方法是否進行了同步處理。

    posted on 2008-03-24 09:05 都市淘沙者 閱讀(280) 評論(0)  編輯  收藏 所屬分類: Java Basic/Lucene/開源資料

    主站蜘蛛池模板: 亚洲欧洲免费无码| 丝袜熟女国偷自产中文字幕亚洲| 黑人粗长大战亚洲女2021国产精品成人免费视频 | 亚洲视频日韩视频| 日韩成全视频观看免费观看高清| 在线播放国产不卡免费视频| 亚洲视频在线观看网址| 又粗又大又硬又爽的免费视频| 久久精品免费一区二区三区| 亚洲中文字幕久久无码| 亚洲无人区午夜福利码高清完整版| 国产人在线成免费视频| 中文字幕在线成人免费看| 中文字幕乱码亚洲无线三区| 亚洲精品成人片在线观看精品字幕 | 亚洲AV综合色区无码一区| 美女被免费视频网站a国产| 一个人免费视频观看在线www| 香蕉大伊亚洲人在线观看| 亚洲精品成人网站在线观看| 日本人的色道www免费一区| 久9久9精品免费观看| 免费国产在线精品一区| 亚洲AV一二三区成人影片| 亚洲国产另类久久久精品小说| 日韩a级毛片免费观看| 6080午夜一级毛片免费看6080夜福利 | 亚洲人成www在线播放| 亚洲AV永久无码精品成人| 国产成人高清精品免费软件| 色影音免费色资源| 亚洲免费人成在线视频观看| 免费精品视频在线| 伊人久久亚洲综合影院首页| 亚洲另类激情综合偷自拍| 中文字幕人成人乱码亚洲电影| 国产区卡一卡二卡三乱码免费| 精品国产污污免费网站aⅴ| 国产成人免费AV在线播放| 久香草视频在线观看免费| 国产天堂亚洲精品|