異步任務——多線程

初始化線程的4種方式:

1、繼承Thread

public class TestThread extends Thread {
    @Override
    public void run() {
        System.out.println("當前線程:" + Thread.currentThread().getName());
        int i = 10 / 2;
        System.out.println("運行結(jié)果:" + i);
    }
    public static void main(String[] args) {
        System.out.println("main start");
        TestThread testThread = new TestThread();
        //啟動線程
        testThread.start();
        System.out.println("main end");
    }
}

main start
main end
當前線程:Thread-0
運行結(jié)果:5

2、實現(xiàn)Runnable接口

public class TestThread2 implements  Runnable{
    public void run() {
        System.out.println("當前線程:" + Thread.currentThread().getName());
        int i = 10 / 2;
        System.out.println("運行結(jié)果:" + i);
    }
    public static void main(String[] args) {
        System.out.println("main start");
        TestThread2 testThread = new TestThread2();
        //啟動線程
        new Thread(testThread).start();
        System.out.println("main end");
    }
}

main start
main end
當前線程:Thread-0
運行結(jié)果:5
實際上Thread類也是實現(xiàn)了Runnable接口

3、實現(xiàn)Callable接口+FutureTask(可以得到返回結(jié)果 ,可以處理異常,jdk1.5以后提供)

public class TestThread3 implements Callable<Integer> {
    public Integer call() throws Exception {
        System.out.println("當前線程:" + Thread.currentThread().getName());
        int i = 10 / 2;
        System.out.println("運行結(jié)果:" + i);
        return i;
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main start");
        FutureTask<Integer> futureTask = new FutureTask<>(new TestThread3());
        new Thread(futureTask).start();
        //阻塞等待整個線程執(zhí)行完成,獲取返回結(jié)果
        Integer result = futureTask.get();
        System.out.println("返回結(jié)果:"+result);
        System.out.println("main end");
    }
}

main start
當前線程:Thread-0
運行結(jié)果:5
返回結(jié)果:5
main end 因為要阻塞等待線程返回結(jié)果,所以主線程最后才結(jié)束

在業(yè)務代碼里面,以上三種啟動線程的方式都不用,應該將所有的異步任務都交給線程池執(zhí)行

4、線程池

創(chuàng)建簡單線程池的4種方式:
ExecutorService service = Executors.newFixedThreadPool();
該方法返回一個固定線程數(shù)量的線程池。該線程池中線程數(shù)量始終 不變。當有一個新的任務提交時,線程池中若有空閑線程,則立即執(zhí)行。若沒有,則新的任務會被暫存在一個任務隊列中,待有線程空閑時,便處理任務隊列中的任務。
缺點:它會創(chuàng)建一個Integer.MAX_VALUE長度的阻塞隊列。
ExecutorService service1 = Executors.newSingleThreadExecutor();
創(chuàng)建一個單線程的線程池,它只會用唯一一個工作線程來執(zhí)行任務
缺點:它會創(chuàng)建一個Integer.MAX_VALUE長度的阻塞隊列。
ExecutorService service2 = Executors.newCachedThreadPool();
創(chuàng)建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程。
缺點:它的最大線程數(shù)量為Integer.MAX_VALUE
ExecutorService service1 = Executors.newScheduledThreadPool()
創(chuàng)建一個定長線程池,支持定時及周期性任務執(zhí)行。
缺點:它的最大線程數(shù)量為Integer.MAX_VALUE

public class TestThread4 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
         //使用線程池可以控制資源,重復利用資源,穩(wěn)定服務器性能。
        //創(chuàng)建一個固定線程數(shù)量的線程池,線程數(shù)量為10。
        ExecutorService service = Executors.newFixedThreadPool(10);
        //提交線程的兩種方式:
        //1.submit(),返回 Future<T>,可以獲取返回結(jié)果
        Future<Integer> submit = service.submit(new TestThread3());
        //2.execute(),無返回值。
        service.execute(new TestThread2());
    }
}

當前線程:pool-1-thread-1
運行結(jié)果:5

線程池七大參數(shù):

  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) 
/**
     * @param corePoolSize
     *       核心線程數(shù)【一直存在,除非設置allowCoreThreadTimeOut】,線程池    
     *       創(chuàng)建好以后就準備就緒的線程數(shù)量,等待執(zhí)行任務
     * @param maximumPoolSize 
     *       線程池允許的最大的線程數(shù)量,可以控制資源
     * @param keepAliveTime 
     *       存活時間,如果當前線程數(shù)量大于核心數(shù)量時,空閑線程釋放時間
     * @param    
     *       keepAliveTime 的時間單位。
     * @param workQueue 
     *       阻塞隊列。如果任務有很多, 就會將目前多的任務放在隊列里面。
     *       只要有線程空閑,就會去隊列里面取出新的任務繼續(xù) 執(zhí)行。
     * @param threadFactory 
     *       線程的創(chuàng)建工廠,可以自定義線程名稱。
     * @param handler 
     *       拒絕策略,如果阻塞隊列滿了,按照我們指定的拒絕策略拒絕執(zhí)行任務。

拒絕策略:
RejectedExecutionHandler提供了四種方式來處理任務拒絕策略:
DiscardOldestPolicy:丟棄隊列中最老的任務
AbortPolicy:拋異常(默認)
CallerRunsPolicy:將任務分給調(diào)用線程來執(zhí)行
DiscardPolicy:直接丟棄

工作順序 :
1、線程池創(chuàng)建,準備好core數(shù)量的核心線程,準備接受任務
2、任務進來,用core中空閑的線程執(zhí)行。
? ?? ? 1)、core線程沒有空閑的,就將再進來的任務放入阻塞隊列中。當core線程空閑就去阻塞隊列獲取任務執(zhí)行。
? ? ? ? 2)、阻塞隊列滿了,就直接開新的線程執(zhí)行,最大只能開到max指定的數(shù)量。
? ? ? ? 3)、所有任務執(zhí)行完畢,大于core線程數(shù)量的空閑線程,會在keepAliveTime指定的時間后,自動銷毀,最終保持到core大小的線程數(shù)量。
4)、如果線程數(shù)已經(jīng)達到max的數(shù)量 ,還有新任務進來,就會使用指定的拒絕策略進行處理。
3、所有的線程創(chuàng)建都是由指定的factory創(chuàng)建。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容