Android開發祕籍學習筆記(二)

  Android中有關線程Thread等相關知識的筆記

線程Thread
  每個應用程序在創建時都會默認運行單一的進程,其中包含所有的任務。爲避免用戶界面被掛起,那些耗時的任務 ,諸如網絡下載或密集的計算,應當駐留於單獨的後臺線程中,如何適當地實現這種操作由開發者決定,但之後則是由Android系統基於開發者的實現來確定線程的優先級。
  大多數應用程序都通過使用線程來提升性能。如果用戶界面的掛起在軟件設計階段沒有被發覺,到了測試階段就會迅速體現出來,因爲Android系統會在用戶界面掛起時彈出警告—告訴用戶Slow app isn’t responding.

Android Thread的使用方法:
  Thread的使用方法主要有兩種方法:其中一種是extends Thread,然後重載Thread的run()函數,另一種是構建一個新的Thread對象,可帶Runnable或不帶。但不管怎麼樣,都是要通過start()函數來運行相應的代碼
構建Thread對象的方法如下:
1、Thread()不代任何參數,該方法會在構建的時候自動生成線程名字。
舉例:

     Thread mThread = new Thread(){
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("This is thread_test");
                super.run();
            }
        };
        mThread.start();
        System.out.println(mThread.getName());

得到的logcat:

04-27 09:22:08.692: INFO/System.out(831): Thread-10
04-27 09:22:08.702: INFO/System.out(831): This is thread_test

2、Thread(Runnable runnable)該函數多了Runnable個對象,被運行的代碼在Runnable對象裏。
舉例:

      Runnable mRunnable = new Runnable(){
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("This is thread with Runnable");
            }

        };
        Thread mThread = new Thread(mRunnable);
        mThread.start();
        System.out.println(mThread.getName());

得到的logcat:

04-27 09:37:47.832: INFO/System.out(865): Thread-11
04-27 09:37:47.861: INFO/System.out(865): This is thread with Runnable

3、Thread(Runnable runnable,String threadName)該函數有Runnable也有自己的名字threadName。
舉例:

     Runnable mRunnable = new Runnable(){
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("This is thread with Runnable and Name");
            }

        };
        Thread mThread = new Thread(mRunnable,"mThreadTest");
        mThread.start();
        System.out.println(mThread.getName());

得到的logcat:

04-27 09:44:03.682: INFO/System.out(900): mThreadTest
04-27 09:44:03.702: INFO/System.out(900): This is thread with Runnable and Name

Runable和Thread的關係
  在java中可有兩種方法實現多線程,一種是繼承Thread類,一種是實現Runnable接口;
1)繼承Thread類的方式

Thread類是在java.lang包中定義的 。一個類只要繼承了Thread類同時覆寫了本類中的run()
步驟就可以實現多線程操作了,然而一個類只能繼承一個父類,這是此種方法的的侷限 。 下面看例子:

class MyThread extends Thread{
    private String name;
    public MyThread(String name) {
    super();
    this.name = name;
    }
    public void run() {
    for(int i=0;i<10;i++) {
    System.out.println("線程開端:"+this.name+",i="+i);
    }
    }
}
public class ThreadDemo01 {
    public static void main(String[] args) {
        MyThread mt1=new MyThread("線程a");
        MyThread mt2=new MyThread("線程b");
        mt1.start();
        mt2.start();
    }
}

2) Runnable接口

  在實際開闢中一個多線程的操作很少 使用Thread類,而是通過Runnable接口實現 。 public interface Runnable{ public void run(); }
例子:

class MyThread implements Runnable{
    private String name;
    public MyThread(String name) {
        this.name = name;
    }
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println("線程開端:"+this.name+",i="+i);
        }
    }
};

  然而在Runnable的子類中沒有start() 方法,只有Thread類中才有 。此時視察Thread類,有一個構造函數:public Thread(Runnable targer) 此構造函數接受Runnable的子類實例,也就是說可以通過Thread類來啓動Runnable實現多線程 。(start() 可以協調系統的資源):

public class ThreadDemo01 {
    public static void main(String[] args) {
        MyThread mt1=new MyThread("線程a");
        MyThread mt2=new MyThread("線程b");
        new Thread(mt1).start();
        new Thread(mt2).start();
    }
}

3)實際中如何應用這兩種實現模式
  在程序實現多線程應優先以實現Runnable接口爲主,由於實現Runnable接口相比繼承Thread類有如下好處:
1.避免點繼承的侷限,一個類可以繼承多個接口 。
2. 利於資源的共享。
以賣票程序爲例,通過Thread類實現:

class MyThread extends Thread {
    private int ticket=10;
    public void run(){
        for(int i=0;i<20;i++) {
            if(this.ticket>0){
                System.out.println("賣票:ticket"+this.ticket--);
            }
        }
    }
};     

下面通過三個線程對象,同時賣票:

public class ThreadTicket {
    public static void main(String[] args) {
        MyThread mt1=new MyThread();
        MyThread mt2=new MyThread();
        MyThread mt3=new MyThread();
        mt1.start();//每個線程都各賣了10張,共賣了30張票
        mt2.start();//但實際只有10張票,每個線程都賣自己的票
        mt3.start();//沒有達到資源共享
    }
}

  假如用Runnable就 可以實現資源共享,下面看例子:

class MyThread implements Runnable{
    private int ticket=10;
    public void run(){
        for(int i=0;i<20;i++){
            if(this.ticket>0){
                System.out.println("賣票:ticket"+this.ticket--);
            }
        }
    }
}


public class RunnableTicket {
public static void main(String[] args) {
    MyThread mt=new MyThread();
    new Thread(mt).start();//同一個mt
    new Thread(mt).start();
    new Thread(mt).start();
}
};

  現在程序中有三個線程,然而一共賣了10張票,也就是說使用Runnable實現多線程可以達到資源共享的目的。

4)Runnable接口和Thread的關係總結
   (1) 說白了就是類和接口的區別。Thread是一個類,java中是不允許繼承多個父類的,這就是Thread的一個侷限性。而使用Runnable就不同了,可以implements多個接口,同時繼承一個父類,這樣會更加靈活。
   (2) 當多個線程需要共享資源時,用Thread很難達到目的,但是用Runnable接口就容易許多了。
  (3) 二者的聯繫:看源碼可以發現,Thread其實就是繼承了Runnable接口的子類。

取消線程
  有時,當一個組件完成或被殺死是,開發者希望有它產生的線程也同樣被殺死,例如在某個Acitivity中定義了線程:
  private …Thread myThread;
myThread.stop()方法已經被棄用了,因爲它會將應用程序置於不可預知的狀態,取而代之的是下面的方法,比如在父組件的onStop()方法中加入

if(myThread != null){
    Thread dummy = myThread;
    myThread = null;
    dummy.interrupt();
}

在應用程序層面上還有另外一種方法來完成相同的工作:使用setDaemon(true)方法將所有生成的線程都聲明爲守護線程,可以確保所有與應用程序關聯的線程在應用程序的主線程終結時,也隨之被殺死。

//use when initially starting a thread
myThread。setDaemon(true);
myThread.start();

設置線程的優先級
  Android系統會處理線程的優先級,默認情況下,一個新線程,如myThread,其優先級被定爲5。開發者可以在myThread.start()執行之前,通過調用myThread.setPriority(priority)來爲線程設定另外的優先級。優先級不能高於Thread.MAX_PRIORITY(10)或者低於Thread.MIN_PRIORITY(1)
  Android還提供了另一種設定線程優先級的方法通過android.os.Process.setThreadPriority (int tid, int priority)

priority:【-20, 19】,高優先級 -> 低優先級。在實際操作中,因爲setThreadPriority 是一個基於“良好的”Linux值得優先級,可以設定的粒度更細,並且對線程的影響也更加明顯。

發佈了41 篇原創文章 · 獲贊 12 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章