線程池
1、線程池,其實就是一個容納多個線程的容器,其中的線程可以反複使用,省去了頻繁建立線程對象的操作,無需反複建立線程而消耗過多資源。(是什麼)
2、那麼,我們為什麼需要用到線程池呢?每次用的時候手動建立不行嗎?
在java中,如果每個請求到達就建立一個新線程,開銷是相當大的。在實際使用中,建立和銷毀線程花費的時間和消耗的系統資源都相當大,甚至可能要比在處理實際的使用者請求的時間和資源要多的多。除了建立和銷毀線程的開銷之外,活動的線程也需要消耗系統資源。如果在一個jvm裡建立太多的線程,可能會使系統由于過度消耗記憶體或“切換過度”而導緻系統資源不足。為了防止資源不足,需要采取一些辦法來限制任何給定時刻處理的請求數目,盡可能減少建立和銷毀線程的次數,特别是一些資源耗費比較大的線程的建立和銷毀,盡量利用已有對象來進行服務。(為什麼)
線程池主要用來解決線程生命周期開銷問題和資源不足問題。通過對多個任務重複使用線程,線程建立的開銷就被分攤到了多個任務上了,而且由于在請求到達時線程已經存在,是以消除了線程建立所帶來的延遲。這樣,就可以立即為請求服務,使用應用程式響應更快;另外,通過适當的調整線程中的線程數目可以防止出現資源不足的情況。(什麼用)
3、線程池都是通過線程池工廠建立,再調用線程池中的方法擷取線程,再通過線程去執行任務方法。
Executors:線程池建立工廠類
public static ExecutorServicenewFixedThreadPool(int nThreads):傳回線程池對象
ExecutorService:線程池類
Future> submit(Runnable task):擷取線程池中的某一個線程對象,并執行
Future 接口:用來記錄線程任務執行完畢後産生的結果。線程池建立與使用
4、這裡介紹兩種使用線程池建立線程的方法
1):使用Runnable接口建立線程池
使用線程池中線程對象的步驟:
1、建立線程池對象
2、建立 Runnable 接口子類對象
3、送出 Runnable 接口子類對象
4、關閉線程池
Test.java 代碼如下:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
//建立線程池對象 參數5,代表有5個線程的線程池
ExecutorService service = Executors.newFixedThreadPool(5);
//建立Runnable線程任務對象
TaskRunnable task = new TaskRunnable();
//從線程池中擷取線程對象
service.submit(task);
System.out.println("----------------------");
//再擷取一個線程對象
service.submit(task);
//關閉線程池
service.shutdown();
}
}
TaskRunnable.java 接口檔案如下:
public class TaskRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("自定義線程任務在執行"+i);
}
}
}
2)使用Callable接口建立線程池
Callable接口:與Runnable接口功能相似,用來指定線程的任務。其中的call()方法,用來傳回線程任務執行完畢後的結果,call方法可抛出異常。
ExecutorService:線程池類
Future submit(Callable task):擷取線程池中的某一個線程對象,并執行線程中的 call() 方法
Future 接口:用來記錄線程任務執行完畢後産生的結果。線程池建立與使用
使用線程池中線程對象的步驟:
1、建立線程池對象
2、建立 Callable 接口子類對象
3、送出 Callable 接口子類對象
4、關閉線程池
Test.java 代碼如下:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test{
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(3);
TaskCallable c = new TaskCallable();
//線程池中擷取線程對象,調用run方法
service.submit(c);
//再擷取一個
service.submit(c);
//關閉線程池
service.shutdown();
}
}
TaskCallable.java 接口檔案如下:
import java.util.concurrent.Callable;
public class TaskCallable implements Callable{
@Override
public Object call() throws Exception {
for (int i = 0; i < 1000; i++) {
System.out.println("自定義線程任務在執行"+i);
}
return null;
}
}
dg5uw
dg5uw
159***[email protected]年前 (2018-03-05)