目錄
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