一、多線程
1、什麼是多線程?
線程是操作系統調度的最小單元,在一個進程裏可以創建多個線程,這些線程擁有各自的計數器、堆棧和局部變量等屬性,並且能夠訪問共享的內存變量。處理器在多線程中高速切換,達到“同時運行”的效果。
2、多線程的創建方式
- 繼承Thread類
- 實現Runnable接口,重寫run()方法
- 實現Callable接口,重寫call方法
3、線程的啓動方式
/**
* 1、繼承Thread
*/
public void createByThread(){
Thread thread = new TestThread();
thread.start();
}
/**
* 2、實現Runnable
*/
public void createByRunnable(){
Thread thread = new Thread(new TestRunnable());
thread.start();
}
/**
* Callable方式
*/
public String createByCallable() throws ExecutionException, InterruptedException {
FutureTask<String> futureTask = new FutureTask<String>(new TestCallable());
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
return futureTask.get();
}
4、線程有什麼狀態
- NEW :初始化狀態,線程被構建,但沒有調用start()方法。
- RUNNABLE :運行狀態,java線程將操作系統中的就緒、運行兩個狀態統稱爲運行狀態
- BLOCKED :阻塞狀態 ,線程阻塞於鎖
- WAITING:等待狀態,線程進入等待狀態,此時需要其他線程做出一下動作(通知或者中斷)
- TIME_WAITING:超時等待狀態,可以在指定時間自動返回
- TERMINATED:終止狀態,線程已經執行完畢。
5、線程如何終止
- 設置flag進行控制,線程代碼運行完畢
- 使用stop方法。現在已經過期不建議用,因爲不保證線程資源正常釋放,通常沒有給予線程完成資源釋放工作的機會,因此會導致程序可能工作在不確定狀態下。
- 結合interrupt和isInterrupted、interrrupted。
- 中斷可以理解爲線程的一個標識位屬性,它表示線程是否被其他線程進行了中斷操作。其他線程調用interrupt()方法對其進行中斷操作。
- 線程自身通過調用isInterrunpted()方法判斷是否被中斷,或者調用靜態方法Thread.interrupted對當前線程的中斷標識進行復位。
二、線程池
1、什麼是線程池?
線程池管理多個線程的創建以及銷燬,可以預先的創建多個線程,將提交上來的任務合理分配給線程執行。線程池可以降低資源消耗,提高響應速度以及提高線程的可管理性。
2、幾種線程池的創建
//創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程(保存60s),若無可回收,則新建線程。
ExecutorService executorService = Executors.newCachedThreadPool();
//創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
ExecutorService executorService2 = Executors.newFixedThreadPool(2);
// 創建一個定長線程池,支持定時及週期性任務執行。
ExecutorService executorService3 = Executors.newScheduledThreadPool(1);
//創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
ExecutorService executorService4 = Executors.newSingleThreadExecutor();
3、線程池的使用
- 調用執行器Executors創建線程池
- 調用submit()或者execute()方法,傳入線程對象
- 當不需要執行線程任務時,調用shutdown關閉線程池
System.out.println("=========線程池的使用=========");
//submit底層調用execute方法執行任務
executorService.submit(new TestThread());
//傳入Runnable
executorService.execute(new TestRunnable());
//傳入Callable 並接收線程返回值
Future<String> future1 = executorService.submit(new TestCallable());
System.out.println("線程池方式啓動Callable結果:"+future1.get());
System.out.println("=====關閉線程池======");
executorService.shutdown();