Android 多線程學習

目錄

1. 什麼是進程,什麼是線程,兩者有何區別

2. 線程生命週期

2.1 Android 主線程與子線程概念理解

3. Java 多線程實例Demo

3.1 繼承Thread

3.2 實現Runnable接口

4. Android 多線程實現

4.1 Handler實現

4.2 HandlerThread實現

4.3 AsyncTask實現

4.4 IntentService實現Demo


1. 什麼是進程,什麼是線程,兩者有何區別

答:進程是cpu資源分配的最小單位。線程是cpu執行調度的最小單位。進程之間不能共享資源,而線程共享所在進程的地址空間和其它資源;一個進程內可擁有多個線程,進程可開啓進程,也可開啓線程;一個線程只能屬於一個進程,線程可直接使用同進程的資源,線程依賴於進程而存在。

詳細的說明轉自 aaronthon博客,內容見下?

什麼是進程?什麼是線程?

進程是系統中正在運行的一個程序,程序一旦運行就是進程。進程是系統資源分配的獨立實體,每個進程都擁有獨立的地址空間。一個進程無法訪問另一個進程的變量和數據結構,如果想讓一個進程訪問另一個進程的資源,需要使用進程間通信,比如管道,文件,套接字等。

一個進程可以擁有多個線程,每個線程使用其所屬進程的棧空間。線程與進程的一個主要區別是,統一進程內的一個主要區別是,同一進程內的多個線程會共享部分狀態,多個線程可以讀寫同一塊內存(一個進程無法直接訪問另一進程的內存)。同時,每個線程還擁有自己的寄存器和棧,其他線程可以讀寫這些棧內存。

線程是進程的一個實體,是進程的一條執行路徑。當一個線程修改了進程的資源,它的兄弟線程可以立即看到這種變化。

進程和線程的區別體現在以下幾個方面:

1.地址空間和其他資源(如打開文件):進程間相互獨立,同一進程的各線程間共享。某進程內的線程在其他進程內不可見。

2.通信:進程間通信IPC(管道,信號量,共享內存,消息隊列),線程間可以直接獨寫進程數據段(如全局變量)來進程通信—— 需要進程同步和互斥手段的輔助,以保證數據的一致性。

3.調度和切換:線程上下文切換比進程上下文切換快得多。

4.在多線程OS中,進程不是一個可執行的實體。

進程和線程的選擇取決以下幾點:

1.需要頻繁創建銷燬的優先使用線程;因爲對進程來說創建和銷燬一個進程的代價是很大的。

2.線程的切換速度快,所以在需要大量計算,切換頻繁時使用線程,還有耗時的操作時用使用線程可提高應用程序的響應。

3.因爲對CPU系統的效率使用上線程更佔優勢,所以可能要發展到多機分佈的用進程,多核分佈用線程。

4.並行操作時用線程,如C/S架構的服務器端併發線程響應用戶的請求。

5.需要更穩定安全時,適合選擇進程;需要速度時,選擇線程更好。

2. 線程生命週期

  • 新建狀態 New status : 創建Thread類的對象且還未調用start()方法,線程進入新建狀態,這時不認爲這線程是活動的狀態
  • 就緒狀態 Runnable status : 線程進入就緒狀態的幾種方式:1. 線程在新建狀態中調用start()方法進入就緒狀態;2. 線程在運行狀態失去CPU資源從而回到就緒狀態;3.  線程從阻塞或等待狀態上回到就緒狀態。處於就緒狀態的線程是活動的線程。
  • 運行狀態 Running status : 線程在就緒狀態上獲得CPU資源,執行run()。
  • 阻塞狀態/等待狀態 Blocked/Waiting status : 處於運行狀態的線程通過調用sleep() | wait() | Input/Output請求 | 同步鎖狀態 進入阻塞/等待狀態。
  • 死亡狀態 Dead status : 當線程成功的執行完run()方法後進入死亡狀態,這時線程不是活的,所以這時你調用start()方法就會跳java.lang.IllegalThreadStateException異常

2.1 Android 主線程與子線程概念理解

在 Android 中,一個進程默認只有一個線程,這個就是我們的主線程,主要負責處理 UI 的工作,以及通過 UI 界面與用戶進行交互,所以當主線程卡頓的時候,就會呈現給用戶界面卡頓的情況,從而用戶覺得 APP 反應遲鈍很“卡”。所以爲了防止出現這種情況,我們開發者應該保證主線程在任何時候都保持着較高的響應速度,即主線程不能做任何耗時的操作(如:網絡請求、I/0操作、數據庫讀寫等),這些耗時的操作需要新建一個線程,即子線程(也叫工作線程)中去處理。

3. Java 多線程實例Demo

Java實現多線程的方法,創建線程類的方法有兩種:一繼承Thread類來,二實現Runnable接口。

3.1 繼承Thread

public class MyThread extends Thread {
	public void run() {
		System.out.println("MyThread run..");
	}
}

public class ThreadTest {
	public static void main(String[] args) {
		MyThread thread = new MyThread();
		thread.start();
	}
}

3.2 實現Runnable接口

public class MyRunnable implements Runnable{
	@Override
	public void run() {
		//放業務邏輯
		System.out.println("MyRunnable run..,");
	}
}

public class MyRunnableTest {
	public static void main(String[] args) {
		Runnable runnable = new MyRunnable();
		Thread thread = new Thread(runnable);
		thread.start();
	}
}

4. Android 多線程實現

子線程不可處理 UI 工作, 任何 UI 工作都需在主線程上處理。

4.1 Handler實現

利用Handler來實現子線程更新UI工作,

具體代碼見下:

public class HandlerAddThread extends AppCompatActivity {
    private TextView mDisplayTv;
    private Handler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_add_thread);

        Button mClickBtn = findViewById(R.id.click_btn);
        mDisplayTv = findViewById(R.id.display_tv);

        //mHandler 用於處理主線程消息隊列中的子線程消息
        mHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == 1) {
                    //更新 UI
                    mDisplayTv.setText("Jere test: User Handler ");
                }
            }
        };

        mClickBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //開啓子線程,子線程處理 UI 工作
                CustomChildThread customThread = new CustomChildThread();
                customThread.start();
            }
        });
    }

    public class CustomChildThread extends Thread {

        @Override
        public void run() {
            //在子線程中創建一個消息對象
            Message childThreadMessage = new Message();
            childThreadMessage.what = 1;
            //將該消息放入主線程的消息隊列中
            mHandler.sendMessage(childThreadMessage);
        }
    }
}

4.2 HandlerThread實現

將工作線程的執行結果傳遞給主線程,從而在主線程中執行相關的 UI 操作,實現工作線程與主線程之間的通信。

Demo例子:利用HandlerThread來實現Progress bar加載,如下圖所示?(按消息隊列順序先後執行:Start Progress Bar 1 ->  Start Progress Bar 2 -> Start Progress Bar 1 )

詳細代碼:

public class HandlerThreadActivity extends AppCompatActivity {
    private final int SET_PROGRESS_BAR_1 = 1;
    private final int SET_PROGRESS_BAR_2 = 2;
    private HandlerThread myHandlerThread;
    private Handler mWorkHandler, mMainHandler;
    private ProgressBar progressBar1, progressBar2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_thread);

        TextView titleTv = findViewById(R.id.title_tv);
        titleTv.setText("HandlerThread");

        progressBar1 = findViewById(R.id.progress_bar_1);
        progressBar2 = findViewById(R.id.progress_bar_2);
        Button startBtn1 = findViewById(R.id.start_progress_bar_1_btn);
        Button startBtn2 = findViewById(R.id.start_progress_bar_2_btn);

        //創建HandlerThread對象
        myHandlerThread = new HandlerThread("myHandlerThread");
        //啓動線程
        myHandlerThread.start();

        //創建Handler關聯主線程,在主線程上執行run(),可以用於執行UI工作
        mMainHandler = new Handler(getMainLooper());

        //創建工作線程Handler,關聯HandlerThread的Looper對象,重寫handleMessage()方法,處理消息
        mWorkHandler = new Handler(myHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);

                switch (msg.what) {
                    case SET_PROGRESS_BAR_1:
                        //設置Progress Bar 1
                        for (int i = 1; i <= 4; i++) {
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }

                            final int progressSchedule = i;
                            mMainHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    progressBar1.setProgress(progressSchedule);
                                }
                            });
                        }
                        break;
                    case SET_PROGRESS_BAR_2:
                        //設置Progress Bar 2
                        for (int i = 1; i <= 4; i++) {
                            try {
                                Thread.sleep(1300);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }

                            final int progressSchedule2 = i;
                            mMainHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    progressBar2.setProgress(progressSchedule2);
                                }
                            });
                        }
                        break;
                    default:
                        break;
                }
            }
        };

        startBtn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //通過mWorkHandler發送處理 progress bar 1 的信息
                Message msg = new Message();
                msg.what = SET_PROGRESS_BAR_1;
                mWorkHandler.sendMessage(msg);
            }
        });

        startBtn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //通過mWorkHandler發送處理 progress bar 2 的信息
                Message msg = new Message();
                msg.what = SET_PROGRESS_BAR_2;
                mWorkHandler.sendMessage(msg);
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        myHandlerThread.quit();
    }
}

4.3 AsyncTask實現

具體代碼請看另一篇博客?Android 多線程之AsyncTask學習

4.4 IntentService實現Demo

具體請看另一篇博客?IntentService例子Demo 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章