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

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

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

    Evan's Blog

    Java, software development and others.

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      28 隨筆 :: 0 文章 :: 73 評論 :: 0 Trackbacks

    Chapter2: Thread Creation and Management

    2.1 What Is a Thread?

    介紹了什么是線程,以及線程(thread, multithread)與進程(process, mutltitask)的區別。其中的一個重要區別是對共享數據的訪問。進程可以共享操作系統級別的某些數據區域,如剪貼板;而線程是對程序自有的數據進行共享。進程之間對共享數據的存取方法是特殊的,因此自然能夠得到程序員的注意;而線程之間對共享數據的存取與對線程自己的數據的存取方法是一樣的,所以常常比較隱蔽,而被程序員忽略。其實,這也是多線程開發比較難的地方。所以,這一節最后說:"A thread, then, is a discrete task that operates on data shared with other threads.(線程就是一個在與其它線程共享的數據上進行操作的單獨任務。)"

    2.2 Creating a Thread

    1. 有兩種方法創建線程:使用Thread類或者Runnable接口
    2. 示例程序竟然是編一個打字游戲,所以,這本書的門檻還是有點高的:(。當然可以從該書的站點直接下載代碼

    3. Thread class
    package java.lang;
    public class Thread implements Runnable {
    public Thread( );
    public Thread(Runnable target);
    public Thread(ThreadGroup group, Runnable target);
    public Thread(String name);
    public Thread(ThreadGroup group, String name);
    public Thread(Runnable target, String name);
    public Thread(ThreadGroup group, Runnable target, String name);
    public Thread(ThreadGroup group, Runnable target, String name,
    long stackSize);
    public void start( );
    public void run( );
    }
    Thread name: 線程名,用以打印線程信息時用,缺省為Thread-N。
    Runnable target:可運行的目標。一個可運行的對象就是一串可由線程執行的指令。缺省就是在run()方法中編寫的內容。
    Thread group:線程組。對于大多數應用來說沒什么意義,缺省在同一組。
    Stack size:線程堆棧大小,與平臺相關。為了使程序更具可移植性,并不推薦使用。

    2.3 The Lifecycle of a Thread

     

    1. Creating a Thread:創建一個線程對象,并沒有開始執行一個線程
    2. Starting a Thread:在調用線程對象的start()方法前,一直處于等待狀態。可以通過調用isAlive()方法來獲取線程是否正在運行;
    3. Terminating a Thread:線程在以下情況下結束  
      1)執行完run()中的語句;
      2)拋出一個異常,包括其沒有捕獲的異常;
      3)其所在的程序(或者容器)調用System.exit()。
    注意:一個線程結束后,就不能再次啟動,該線程就變成一個普通的對象,如果試圖再次調用start()方法,將拋出java.lang.IllegalThreadStateException異常。如果想多次運行,要么創建新的對象;要么就是不要結束該線程。
    4. Java并沒有提供可靠的方法來暫停、掛起或者重啟一個線程的方法,線程本身能通過sleep()函數來暫停執行。目前依然只能確保若干毫秒級別的精度。
    5. Thread Cleanup:線程終止后,線程對象依然存在。可以通過join()方法以阻塞方式(blocked)來等待某個線程終止。

    2.4 Two Approches to Stop a Thread

    1. Setting a Flag:在線程的執行過程中判斷其它線程是否將標志置位。其缺點是有時間延遲,尤其是當進入了某些被阻塞的函數如:sleep(), wait()等;
    2. 調用線程的interrupt()方法,線程的執行過程中改為判斷isInterrupted()的返回值。可以解決線程進入阻塞導致的延遲,但依然解決不了超長時間計算而導致的延遲。interrupt()有兩個作用:1)終止sleep()和wait(),拋出InterruptedException;2)使isInterrupted()返回true。下面這段代碼將演示interrupt()的作用:

    public class TestInterrupted {
    public static void main(String args[]) throws InterruptedException{
    Foo foo = new Foo();
    foo.start();
    Thread.currentThread().sleep(100); //注釋掉這句有什么影響呢?
    System.out.println("before interrupt");
    foo.interrupt();
    System.out.println("after interrupt");
    } }

    class Foo extends Thread {
    public void run() {
    try{
    while(!isInterrupted()) {
    System.out.println("start calculating...");
    double pi = 3.1415926;
    for(int i=0; i<5; i++) {
    for(long j=0; j<1000000; j++) {
    pi *= pi;
    }
    System.out.println("i="+i);
    }
    System.out.println("before sleep");
    sleep(5000); //注釋掉這句及相關的try...catch語句,又怎樣呢?
    System.out.println("after sleep");
    }
    } catch(InterruptedException ex) {
    ex.printStackTrace(System.out);
    }
    }
    }

     

    2.5 The Runnable Interface

    為什么有了Thread類,還要有Runnable接口呢?最主要的原因是為了解決Java不能多重繼承的問題。線程繼承自Thread,還是僅僅實現Runnable接口,取決于這個線程的作用。不過,如果僅僅實現Runnable接口,則在線程里不能使用Thread類的方法,比如interrupt()和isInterrupted()。當然,這個還是要取決于實際情況。

    2.6 Threads and Objects

    主要講解線程與對象的關系。線程根本上還是個對象,其可以存取任何對象包括其它線程對象,當然也能被其它對象存取,只要沒有因為爭奪公共資源而被鎖定,線程對象中的任何屬性和方法都有可能同時執行。并且Java中的鎖只針對對象本身,并不包括對象下的屬性;而對方法同步,則等同于對對象同步。更進一步的說明還可以參考《Practical Java》中的"實踐46:面對instance函數,synchronized鎖定的是對象(object)而非函數(methods)或代碼(code)"。下面用兩段代碼來說明一下:
    代碼1:

    public class TestLock {
    public static void main(String args[])
    throws InterruptedException{
    Foo foo = new Foo();
    foo.start();
    Thread t = Thread.currentThread();
    for(int i=0; i<10; i++) {
    foo.setInt2("Main", i, i+20);
    }
    }
    }

    class Foo extends Thread{
    protected int arrI[] = new int[10];

    public void run() {
    try {
    for(int i=0; i<10; i++) {
    setInt("Foo", i, i);
    }
    } catch(InterruptedException ex) {}
    }

    public synchronized void setInt(String from, int pos, int val)
    throws InterruptedException{
    arrI[pos] = val;
    sleep((long)(Math.random()*5000));
    System.out.println(from+":arrI["+pos+"]="+arrI[pos]);
    }

    public void setInt2(String from, int pos, int val)
    throws InterruptedException {
    synchronized(arrI){
    arrI[pos] = val;
    sleep((long)(Math.random()*5000));
    System.out.println(from+":arrI["+pos+"]="+arrI[pos]);
    }
    }
    }
    結果:非線程安全,setInt()在對象上加鎖,而setInt2()在屬性arrI上加鎖,不同的鎖不能保證線程安全。可能的結果如下:
    Foo:arrI[0]=0 
    Main:arrI[0]=0
    Main:arrI[1]=21
    Main:arrI[2]=22
    Foo:arrI[1]=21
    Main:arrI[3]=23
    Main:arrI[4]=24
    Main:arrI[5]=25
    Foo:arrI[2]=2
    Main:arrI[6]=26
    Main:arrI[7]=27
    Foo:arrI[3]=3
    Foo:arrI[4]=4
    Main:arrI[8]=28
    Main:arrI[9]=29
    Foo:arrI[5]=5
    Foo:arrI[6]=6
    Foo:arrI[7]=7
    Foo:arrI[8]=8
    Foo:arrI[9]=9

    代碼2:
    public class TestLock1 {
    public static void main(String args[])
    throws InterruptedException{
    Foo1 foo = new Foo1();
    foo.start();
    Thread t = Thread.currentThread();
    for(int i=0; i<10; i++) {
    foo.setInt2("Main", i, i+20);
    }
    }
    }

    class Foo1 extends Thread{
    protected int arrI[] = new int[10];

    public void run() {
    try{
    for(int i=0; i<10; i++) {
    setInt("Foo", i, i);
    }
    }catch(InterruptedException ex){}
    }

    public synchronized void setInt(String from, int pos, int val)
    throws InterruptedException{
    arrI[pos] = val;
    sleep((long)(Math.random()*5000));
    System.out.println(from+":arrI["+pos+"]="+arrI[pos]);
    }

    public synchronized void setInt2(String from, int pos, int val)
    throws InterruptedException{
    arrI[pos] = val;
    sleep((long)(Math.random()*5000));
    System.out.println(from+":arrI["+pos+"]="+arrI[pos]);
      }
    }
    結果:線程安全
    posted on 2006-03-05 23:25 Evan 閱讀(692) 評論(0)  編輯  收藏 所屬分類: Java筆記
    主站蜘蛛池模板: 亚洲精品亚洲人成在线麻豆| 亚洲国产成人高清在线观看 | 可以免费看黄视频的网站| 亚洲国产精品久久久天堂| 国产成人无码区免费网站| 亚洲中文字幕无码一区| 男女一边摸一边做爽的免费视频| 亚洲一区二区精品视频| 成av免费大片黄在线观看| 亚洲国产精品无码中文字| 99ee6热久久免费精品6| 亚洲一区二区三区在线观看蜜桃| 91手机看片国产永久免费| 亚洲小说图区综合在线| 国产成人无码区免费A∨视频网站 国产成人涩涩涩视频在线观看免费 | 在线视频免费观看高清| 亚洲色无码专区一区| 午夜国产大片免费观看| 中文在线免费观看| 亚洲综合成人网在线观看| 亚洲第一成年免费网站| 无忧传媒视频免费观看入口| 久久久久久久亚洲Av无码 | 精品在线观看免费| 国产AV无码专区亚洲AV漫画 | 国产精品国产免费无码专区不卡| 欧亚一级毛片免费看| 亚洲国产另类久久久精品小说 | 99爱在线精品视频免费观看9| 亚洲av永久无码嘿嘿嘿| 全部免费毛片在线| 国产免费无码一区二区| 亚洲香蕉久久一区二区| 亚洲人成无码网WWW| 最近高清中文字幕免费| 狠狠入ady亚洲精品| 亚洲第一福利网站| 国产成人无码区免费A∨视频网站 国产成人涩涩涩视频在线观看免费 | 国产老女人精品免费视频| 久久精品国产免费| 亚洲日韩国产一区二区三区在线|