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

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

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

    Picses' sky

    Picses' sky
    posts - 43, comments - 29, trackbacks - 0, articles - 24

    用Java線程獲取優異性能(I)2

    Posted on 2007-07-18 13:04 Matthew Chen 閱讀(233) 評論(0)  編輯  收藏 所屬分類: Java MultiThread

    怎樣使用名稱
    在一個調試會話期間,使用用戶友好方式從另一個線程區別其中一個線程證明是有幫助的。要區分其中一個線程,Java給一個線程取一個名稱。Thread缺省的名稱是一個短線連字符和一個零開始的數字符號。你可以接受Java的缺省線程名稱或選擇使用你自己的。為了能夠自定義名稱,Thread提供帶有name參數和一個setName(String name)方法的構造器。Thread也提供一個getName()方法返回當前名稱。表2顯示了怎樣通過Thread(String name)創建一個自定義名稱和通過在run()方法中調用getName()檢索當前名稱:
    表2.NameThatThread.java
    // NameThatThread.java
    class NameThatThread
    {
    public static void main (String [] args)
    {
    MyThread mt;
    if (args.length == 0)
    mt = new MyThread ();
    else
    mt = new MyThread (args [0]);
    mt.start ();
    }
    }
    class MyThread extends Thread
    {
    MyThread ()
    {
    //編譯器創建等價于super()的字節代碼
    }
    MyThread (String name)
    {
    super (name); //將名稱傳遞給Thread超類
    }
    public void run ()
    {
    System.out.println ("My name is: " + getName ());
    }
    }
    你能夠在命令行向MyThread傳遞一個可選的name參數。例如,java NameThatThread X 建立X作為線程的名稱。如果你指定一個名稱失敗,你將看到下面的輸出:
    My name is: Thread-1
    如果你喜歡,你能夠在MyThread(String name)構造器中將super(name)調用改變成setName(String name)調用——作為setName(name)后一種方法調用達到同樣建立線程名稱的目的——作為super(name)我作為練習保留給你們。
    注意
    Java主要將名稱指派給運行main() 方法的線程,開始線程。你特別要看看當開始線程擲出一個例外對象時在線程“main”的例外顯示的JVM的缺省例外處理打印消息。
    休眠或停止休眠
    在這一欄后面,我將向你介紹動畫——在一個表面上重復畫圖形,這稍微不同于完成一個運動畫面。要完成動畫,一個線程必須在它顯示兩個連續畫面時中止。調用Thread的靜態sleep(long millis)方法強迫一個線程中止millis毫秒。另一個線程可能中斷正在休眠的線程。如果這種事發生,正在休眠的線程將醒來并從sleep(long millis)方法擲出一個InterruptedException對象。結果,調用sleep(long millis)的代碼必須在一個try代碼塊中出現——或代碼方法必須在自己的throws子句中包括InterruptedException。
    為了示范sleep(long millis),我寫了一個CalcPI1應用程序。這個應用程序開始了一個新線程便于用一個數學運算法則計算數學常量pi的值。當新線程計算時,開始線程通過調用sleep(long millis)中止10毫秒。在開始線程醒后,它將打印pi的值,其中新線程存貯在變量pi中。表3給出了CalcPI1的源代碼:
    表3. CalcPI1.java
    // CalcPI1.java
    class CalcPI1
    {
    public static void main (String [] args)
    {
    MyThread mt = new MyThread ();
    mt.start ();
    try
    {
    Thread.sleep (10); //休眠10毫秒
    }
    catch (InterruptedException e)
    {
    }
    System.out.println ("pi = " + mt.pi);
    }
    }
    class MyThread extends Thread
    {
    boolean negative = true;
    double pi; //缺省初始化為0.0
    public void run ()
    {
    for (int i = 3; i < 100000; i += 2)
    {
    if (negative)
    pi -= (1.0 / i);
    else
    pi += (1.0 / i);
    negative = !negative;
    }
    pi += 1.0;
    pi *= 4.0;
    System.out.println ("Finished calculating PI");
    }
    }
    如果你運行這個程序,你將看到輸出如下(但也可能不一樣):
    pi = -0.2146197014017295
    完成計算PI
    為什么輸出不正確呢?畢竟,pi的值應近似等于3.14159。回答是:開始線程醒得太快了。在新線程剛開始計算pi時,開始線程就醒過來讀取pi的當前值并打印其值。我們可以通過將10毫秒延遲增加為更長的值來進行補償。這一更長的值(不幸的是它是依賴于平臺的)將給新線程一個機會在開始線程醒過來之前完成計算。(后面,你將學到一種不依賴平臺的技術,它將防止開始線程醒來直到新線程完成。)
    注意
    線程同時提供一個sleep(long millis, int nanos)方法,它將線程休眠millis 毫秒和nanos 納秒。因為多數基于JVM的平臺都不支持納秒級的分解度,JVM 線程處理代碼將納秒數字四舍五入成毫秒數字的近似值。如果一個平臺不支持毫秒級的分解度,JVM 線程處理代碼將毫秒數字四舍五入成平臺支持的最小級分解度的近似倍數。
    它是死的還是活的?
    當一個程序調用Thread的start()方法時,在一個新線程調用run()之前有一個時間段(為了初始化)。run()返回后,在JVM清除線程之前有一段時間通過。JVM認為線程立即激活優先于線程調用run(),在線程執行run()期間和run()返回后。在這時間間隔期間,Thread的isAlive()方法返回一個布爾真值。否則,方法返回一個假值。
    isAlive()在一個線程需要在第一個線程能夠檢查其它線程的結果之前等待另一個線程完成其run()方法的情形下證明是有幫助的。實質上,那些需要等待的線程輸入一個while循環。當isAlive()為其它線程返回真值時,等待線程調用sleep(long millis) (或 sleep(long millis, int nanos))周期性地休眠 (避免浪費更多的CPU循環)。一旦isAlive()返回假值,等待線程便檢查其它線程的結果。
    你將在哪里使用這樣的技術呢?對于起動器,一個CalcPI1的修改版本怎么樣,在打印pi的值前開始線程在哪里等待新線程的完成?表4的CalcPI2源代碼示范了這一技術:
    表4. CalcPI2.java
    // CalcPI2.java
    class CalcPI2
    {
    public static void main (String [] args)
    {
    MyThread mt = new MyThread ();
    mt.start ();
    while (mt.isAlive ())
    try
    {
    Thread.sleep (10); //休眠10毫秒
    }
    catch (InterruptedException e)
    {
    }
    System.out.println ("pi = " + mt.pi);
    }
    }
    class MyThread extends Thread
    {
    boolean negative = true;
    double pi; //缺省初始化成0.0
    public void run ()
    {
    for (int i = 3; i < 100000; i += 2)
    {
    if (negative)
    pi -= (1.0 / i);
    else
    pi += (1.0 / i);
    negative = !negative;
    }
    pi += 1.0;
    pi *= 4.0;
    System.out.println ("Finished calculating PI");
    }
    }
    CalcPI2的開始線程在10毫秒時間間隔休眠,直到mt.isAlive ()返回假值。當那些發生時,開始線程從它的while循環中退出并打印pi的內容。如果你運行這個程序,你將看到如下的輸出(但不一定一樣):
    完成計算PI
    pi = 3.1415726535897894
    這不,現在看上去更精確了?
    注意
    一個線程可能對它自己調用isAlive() 方法。然而,這毫無意義,因為isAlive()將一直返回真值。
    合力
    因為while循環/isAlive()方法/sleep()方法技術證明是有用的,Sun將其打包進三個方法組成的一個組合里:join(),join(long millis)和join(long millis, int nanos)。當當前線程想等待其它線程結束時,經由另一個線程的線程對象引用調用join()。相反,當它想其中任意線程等待其它線程結束或等待直到millis毫秒和nanos納秒組合通過時,當前線程調用join(long millis)或join(long millis, int nanos)。(作為sleep()方法,JVM 線程處理代碼將對join(long millis)和join(long millis,int nanos)方法的參數值四舍五入。)表5的CalcPI3源代碼示范了一個對join()的調用:
    表5. CalcPI3.java
    // CalcPI3.java
    class CalcPI3
    {
    public static void main (String [] args)
    {
    MyThread mt = new MyThread ();
    mt.start ();
    try
    {
    mt.join ();
    }
    catch (InterruptedException e)
    {
    }
    System.out.println ("pi = " + mt.pi);
    }
    }
    class MyThread extends Thread
    {
    boolean negative = true;
    double pi; //缺省初始化成0.0
    public void run ()
    {
    for (int i = 3; i < 100000; i += 2)
    {
    if (negative)
    pi -= (1.0 / i);
    else
    pi += (1.0 / i);
    negative = !negative;
    }
    pi += 1.0;
    pi *= 4.0;
    System.out.println ("Finished calculating PI");
    }
    }
    CalcPI3的開始線程等待與MyThread對象有關被mt引用的線程結束。接著開始線程打印pi的值,其值與CalcPI2的輸出一樣。
    警告
    不要試圖將當前線程與其自身連接,因為這樣當前線程將要永遠等待。

    主站蜘蛛池模板: 亚洲日韩国产精品第一页一区| 国产乱子伦精品免费视频| 亚洲人成中文字幕在线观看| 巨胸喷奶水视频www网免费| 无码国产精品一区二区免费vr | 美女被cao网站免费看在线看| 亚洲aⅴ无码专区在线观看春色| 亚洲精品中文字幕麻豆| 亚洲三区在线观看无套内射| 日本特黄a级高清免费大片| 亚洲一级免费视频| 久久久久久国产精品免费免费男同 | 亚洲综合色丁香婷婷六月图片 | 日本高清不卡aⅴ免费网站| 自拍偷自拍亚洲精品播放| 久久精品国产亚洲AV忘忧草18| 亚洲第一精品在线视频| 亚洲理论电影在线观看| 亚洲狠狠爱综合影院婷婷| 国产日产成人免费视频在线观看| 美女视频黄是免费的网址| 亚洲w码欧洲s码免费| 亚洲电影在线免费观看| 国产精品成人免费福利| 91短视频免费在线观看| jjizz全部免费看片| 亚洲精品在线免费观看视频| 精品国产污污免费网站aⅴ| 无码av免费一区二区三区试看| 国产免费AV片在线观看| 日本亚洲欧洲免费天堂午夜看片女人员| 国产高清对白在线观看免费91 | 亚洲av永久无码精品表情包| 国产成A人亚洲精V品无码性色| 亚洲无线码在线一区观看| 亚洲人成网7777777国产| 亚洲AV无码一区二区乱孑伦AS| 亚洲AV日韩AV永久无码免下载| 亚洲AV区无码字幕中文色| 亚洲精品熟女国产| 国产精品亚洲午夜一区二区三区|