25_線程池_幾個常見的線程池

【線程池簡述】java

線程池中,當須要使用線程時,會從線程池中獲取一個空閒線程,線程完成工做時,不會直接關閉線程,而是將這個線程退回到池子,方便其它人使用。框架

簡而言之,使用線程池後,原來建立線程變成了從線程池得到空閒線程,關閉線程變成了向池子歸還線程。ide

 

【線程池帶來的好處】性能

1.下降資源消耗,經過重複利用已建立的線程下降線程建立和銷燬形成的性能消耗。ui

2.提升響應速度,當任務到達時,任務能夠不須要等待線程建立,能夠直接執行。spa

3.提升線程的可管理性,線程是稀缺資源,若是無限制地建立,不只會消耗系統資源,還會下降系統的穩定性,使用線程池能夠進行統一的分配,調優和監控。線程

 

【線程池接口、類關係一覽】 code

 

【說明】對象

Executor是一個頂級接口,它裏面只聲明一個方法:execute(Runnable command),用來執行傳進去的任務。blog

ExecutorService接口繼承了Executor接口,並聲明瞭一些方法:submit、shutdown、invokeAll等。

AbstractExecutorService抽象類實現了ExecutorService接口,基本實現了ExecutorService接口的全部方法。

ThreadPoolExecutor繼承了類AbstractExecutorService。

 

【Executors框架】

Executors框架提供了各類類型的線程池,主要有如下幾種工廠方法:

[ newFixedThreadPool()方法 ]

該方法返回一個固定線程數量的線程池。該線程池中的線程數量始終不變,當有一個新的任務提交時,線程池中如有空閒線程,則當即處理。

若沒有空閒線程,則新的任務會被暫存在一個任務隊列中,待有線程空閒時,便處理在任務隊列中的任務。

[ newSingleThreadExecutor()方法 ]

該方法返回一個只有一個線程的線程池。

若多多餘一個任務被提交到該線程池,任務會被保存在一個任務隊列中,待線程空閒,按先入先出順序執行任務。

[ newCachedThreadPool()方法 ]

該方法返回一個可具實際狀況調整線程數量的線程池,線程池的線程數量不肯定,但如有空閒線程能夠複用,則會有優先使用而能夠複用線程。若全部線程均在工做,又有新的任務提交,則會建立新的現場處理任務。全部線程在當前任務執行完畢後,將返回線程池進行復用。

[ newSingleThreadScheduledExecutor()方法 ]

該方法返回一個ScheduleExecutorService對象,線程池大小爲1

ScheduleExecutorService接口在ExecutorService接口之上擴張了在給定時間執行某任務的功能,如:在某個固定的延時以後執行,或者週期性執行某個任務。

[ newScheduleThreadPool()方法 ]

該方法返回一個ScheduleExecutorService對象,但該線程池能夠指定線程數量

 

【固定大小的線程池——newFixedThreadPool()】

package com.test.executor;

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

public class ExecutorDemo1 {
    
    public static void main(String[] args) {
        MyTask task = new MyTask();
        ExecutorService es = Executors.newFixedThreadPool(5);  //建立固定線程數大小爲5的線程池
        for(int i=0;i<10;i++){   //依次向線程池提交了10個任務
            es.submit(task);
        }
    }
}

class MyTask implements Runnable{

    @Override
    public void run() {
        System.out.println(System.currentTimeMillis()+":Thread ID:"+Thread.currentThread().getId());
        try{
            Thread.sleep(1000); //1秒
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    
}

【運行結果】

 

【只有一個線程的線程池——newSingleThreadExecutor()】 

package com.test.executor;

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

/**
 * Created by HigginCui on 2018/4/14.
 */
public class ExecutorDemo1 {

    public static void main(String[] args) {
        MyTask myTask = new MyTask();
        //只有一個線程的線程池
        ExecutorService es = Executors.newSingleThreadExecutor();
        for(int i=0;i<10;i++){
            es.submit(myTask);
        }
    }
}

class MyTask implements Runnable{
    @Override
    public void run() {
        System.out.println(System.currentTimeMillis()/1000 + ":Thread ID:" + Thread.currentThread().getId());
        try {
            Thread.sleep(1000);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

【運行結果】

 

【可根據實際狀況調整線程數量的線程池——newCacheThreadPool()】

package com.test.executor;

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

/**
 * Created by HigginCui on 2018/4/14.
 */
public class ExecutorDemo1 {

    public static void main(String[] args) {
        MyTask myTask = new MyTask();
        //可根據實際狀況調整線程數量的線程池
        ExecutorService es = Executors.newCachedThreadPool();
        for(int i=0;i<10;i++){
            es.submit(myTask);
        }
    }
}

class MyTask implements Runnable{
    @Override
    public void run() {
        System.out.println(System.currentTimeMillis()/1000 + ":Thread ID:" + Thread.currentThread().getId());
        try {
            Thread.sleep(1000);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

【運行結果】

 

【計劃定時任務——newScheduledThreadPool】

package com.test.executor;

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

/**
 * Created by HigginCui on 2018/4/14.
 */
public class ExecutorDemo1 {

    public static void main(String[] args) {

        ScheduledExecutorService ses = Executors.newScheduledThreadPool(10);
        /**
         * scheduleAtFixedRate方法 :若是前面的任務沒有完成,則調度也不會執行!
         * scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
         */
        ses.scheduleAtFixedRate(new ScheduledTimeTask(), 0, 2, TimeUnit.SECONDS);  //設置每定時2s執行一次
    }

}

class ScheduledTimeTask implements Runnable {
    @Override
    public void run() {
        try {
            //修改這裏的任務執行時間
            Thread.sleep(1000);
            System.out.println( System.currentTimeMillis() / 1000 + " : ThreadId = " + Thread.currentThread().getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

【設置任務的執行時間爲1s( <定時的2s )的運行結果】

【設置任務的執行時間爲3s( <定時的2s )的運行結果(即代碼改爲Thread.sleep(3000))】

相關文章
相關標籤/搜索