1. 程式人生 > >java高並發編程(五)線程池

java高並發編程(五)線程池

pen style shutdown return turn lock close print dfa

摘自馬士兵java並發編程

一、認識Executor、ExecutorService、Callable、Executors

技術分享圖片
/**
 * 認識Executor
 */
package yxxy.c_026;

import java.util.concurrent.Executor;

public class T01_MyExecutor implements Executor {

    public static void main(String[] args) {
        new T01_MyExecutor().execute(new Runnable(){

            @Override
            
public void run() { System.out.println("hello executor"); } }); } @Override public void execute(Runnable command) { //new Thread(command).run(); command.run(); } }
View Code Executor執行器是一個接口,只有一個方法execute執行任務,在java的線程池的框架裏邊,這個是最頂層的接口; ExecutorService:從Executor接口繼承。 Callable:裏面call方法,和Runnable接口很像,設計出來都是被其他線程調用的;但是Runnable接口裏面run方法是沒有返回值的也不能拋出異常;而call方法有返回值可以拋異常; Executors: 操作Executor的一個工具類;以及操作ExecutorService,ThreadFactory,Callable等; 二、ThreadPool:      
技術分享圖片
/**
 * 線程池的概念
 */
package yxxy.c_026;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class T05_ThreadPool {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newFixedThreadPool(5); //
execute submit for (int i = 0; i < 6; i++) { service.execute(() -> { try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()); }); } System.out.println(service); service.shutdown(); System.out.println(service.isTerminated()); System.out.println(service.isShutdown()); System.out.println(service); TimeUnit.SECONDS.sleep(5); System.out.println(service.isTerminated()); System.out.println(service.isShutdown()); System.out.println(service); } }
View Code

console:

技術分享圖片
java.util.concurrent.ThreadPoolExecutor@53d8d10a[Running, pool size = 5, active threads = 5, queued tasks = 1, completed tasks = 0]
false
true
java.util.concurrent.ThreadPoolExecutor@53d8d10a[Shutting down, pool size = 5, active threads = 5, queued tasks = 1, completed tasks = 0]
pool-1-thread-1
pool-1-thread-3
pool-1-thread-2
pool-1-thread-5
pool-1-thread-4
pool-1-thread-1
true
true
java.util.concurrent.ThreadPoolExecutor@53d8d10a[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 6]
View Code 創建了一個線程池,扔了5個線程,接下來要執行6個任務,扔進去線程池裏面就啟一個線程幫你執行一個,因為這裏最多就起5個線程,接下來扔第6個任務的時候,不好意思,它排隊了,排在線程池所維護的一個任務隊列裏面,任務隊列大多數使用的都是BlockingQueue,這是線程池的概念; 有什麽好處?好處在於如果這個任務執行完了,這個線程不會消失,它執行完任務空閑下來了,如果有新的任務來的時候,直接交給這個線程來運行就行了,不需要新啟動線程;從這個概念上講,如果你的任務和線程池線程數量控制的比較好的情況下,你不需要啟動新的線程就能執行很多很多的任務,效率會比較高,並發性好; service.shutdown():關閉線程池,shutdown是正常的關閉,它會等所有的任務都執行完才會關閉掉;還有一個是shutdownNow,二話不說直接就給關了,不管線程有沒有執行完; service.isTerminated(): 代表的是這裏所有執行的任務是不是都執行完了。isShutdown()為true,註意它關了但並不代表它執行完了,只是代表正在關閉的過程之中(註意打印Shutting down) 打印5個線程名字,而且第一個線程執行完了之後,第6個任務來了,第1個線程繼續執行,不會有線程6; 當所有線程全部執行完畢之後,線程池的狀態為Terminated,表示正常結束,complete tasks=6 線程池裏面維護了很多線程,等著你往裏扔任務,而扔任務的時候它可以維護著一個任務列表,還沒有被執行的任務列表,同樣的它還維護著另外一個隊列,complete tasks,結束的任務隊列,任務執行結束扔到這個隊列裏,所以,一個線程池維護著兩個隊列; 三、Future 技術分享圖片
/**
 * 認識future
 */
package yxxy.c_026;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

public class T06_Future {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        /*FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>(){
            @Override
            public Integer call() throws Exception {
                TimeUnit.MILLISECONDS.sleep(3000);
                return 1000;
            }
        });*/
        
        FutureTask<Integer> task = new FutureTask<>(()->{
            TimeUnit.MILLISECONDS.sleep(3000);
            return 1000;
        });
        
        new Thread(task).start();
        
        System.out.println(task.get()); //阻塞
        
        //*******************************
        ExecutorService service = Executors.newFixedThreadPool(5);
        Future<Integer> f = service.submit(()->{
            TimeUnit.MILLISECONDS.sleep(5000);
            return 1;
        });
        System.out.println(f.isDone());
        System.out.println(f.get());
        System.out.println(f.isDone());
        
    }
}
View Code 技術分享圖片
1000
false
1
true
View Code Future: ExecutorService裏面有submit方法,它的返回值是Future類型,因為你扔一個任務進去需要執行一段時間,未來的某一個時間點上,任務執行完了產生給你一個結果,這個Future代表的就是那個Callable的返回值; ---------------

java高並發編程(五)線程池