亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

通過Java講解ThreadPool線程池的示例

發布時間:2021-03-03 11:04:37 來源:億速云 閱讀:348 作者:清風 欄目:編程語言

這篇文章主要為大家展示了通過Java講解ThreadPool線程池的示例,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶大家一起來研究并學習一下“通過Java講解ThreadPool線程池的示例”這篇文章吧。

Java的特點有哪些

Java的特點有哪些 1.Java語言作為靜態面向對象編程語言的代表,實現了面向對象理論,允許程序員以優雅的思維方式進行復雜的編程。 2.Java具有簡單性、面向對象、分布式、安全性、平臺獨立與可移植性、動態性等特點。 3.使用Java可以編寫桌面應用程序、Web應用程序、分布式系統和嵌入式系統應用程序等。

ThreadPool線程池

  • 1.線程池的優勢


    • 1.1.引言

    • 1.2.為什么要使用線程池

  • 2.線程池的使用


    • 2.2.1.newFixedThreadPool(int)方法

    • 2.2.2.newSingleThreadExector

    • 2.2.3.newCachedThreadPool

    • 2.1.架構說明

    • 2.2.線程池的三大方法


  • 3.ThreadPoolExecutor底層原理

  • 4.線程池7大重要參數

1.線程池的優勢

1.1.引言

與數據庫線程池類似,如果沒有數據庫連接池,那么每次對數據庫的連接池都要new來獲取連接池。重復的連接和釋放操作會消費大量的系統資源,我們可以使用數據庫連接池,直接去池中取連接池。
同樣,在沒有線程池之前,我們也是通過new Thread.start()來獲取線程,現在我們也不需要new了,這樣就能實現復用,使得我們系統變得更加高效。

1.2.為什么要使用線程池

例子:

  • 10年前單核CPU電腦,假的多線程,像馬戲團小丑玩多個球,CPU需要來回切換。

  • 現在是多核電腦,多個線程各自跑在獨立的CPU上,不用切換效率高。

線程池的優勢:

線程池做的工作只要是控制運行的線程數量,處理過程中將任務放入隊列,然后在線程創建后啟動這些任務,如果線程數量超過了最大數量,超出數量的線程排隊等候,等其他線程執行完畢,再從隊列中取出任務來執行。

它的主要特點為:

  • 線程復用

  • 控制最大并發數

  • 管理線程

優點:

  • 第一:降低資源消耗。通過重復利用已創建的線程降低線程創建和銷毀造成的銷耗。

  • 第二:提高響應速度。當任務到達時,任務可以不需要等待線程創建就能立即執行。

  • 第三:提高線程的可管理性。線程是稀缺資源,如果無限制的創建,不僅會銷耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配,調優和監控。

2.線程池的使用

2.1.架構說明

Executor 框架是什么?

Java Doc中是這么描述的

An object that executes submitted Runnable tasks. This interface provides a way of decoupling task submission from the mechanics of how each task will be run, including details of thread use, scheduling, etc. An Executor is normally used instead of explicitly creating threads.

執行提交的Runnable任務的對象。這個接口提供了一種將任務提交與如何運行每個任務的機制,包括線程的詳細信息使用、調度等。通常使用Executor而不是顯式地創建線程。

Java中的線程池是通過Executor框架實現的,,該框架中用到了Executor,Executors,ExecutorService,ThreadPoolExecutor這幾個類。而我們常用的接口是ExecutorService子接口Executors是線程的工具類(類似數組的工具類Arrays,集合的工具類Collections)ThreadPoolExecutor是這些類的重點我們可以通過輔助工具類Executors拿到ThreadPoolExecutor線程池
通過Java講解ThreadPool線程池的示例
各個類更加詳細的介紹如下:

Executor所有線程池的接口,只有一個方法,該接口定義執行Runnable任務的方式
ExecutorService 增加Executor的行為,是Executor實現類的最直接的接口,該接口定義提供對Executor的服務
Executors 線程池工廠類,提供了一系列工廠方法用于創建線程池,返回的線程池都實現了
ScheduledExecutorService:定時調度接口。
AbstractExecutorService 執行框架抽象類。
ThreadPoolExecutor JDK中線程池的具體實現,一般用的各種線程池都是基于這個類實現的

2.2.線程池的三大方法

2.2.1.newFixedThreadPool(int)方法

Exectors.newFixedThreadPool(int) -->執行長期任務性能好,創建一個線程池,一池有N個固定的線程,有固定線程數的線程

	public static void main(String[] args) {
		//一池5個受理線程,類似一個銀行5個受理窗口。不管你現在多少個線程,都只有5個
		ExecutorService threadPool=Executors.newFixedThreadPool(5); 
		
		try {
			//模擬有10個顧客過來銀行辦理業務,目前池子里面有5個工作人員提供服務。
			for(int i=1;i<=10;i++){
				//execute方法里面有一個參數,參數類型是Runnable,Runnable是函數式接口,可以用lambda表達式,并且runnable就是這10個顧客
				threadPool.execute(()->{
					System.out.println(Thread.currentThread().getName()+"\t 辦理業務");
				});
			}
		} catch (Exception e) {
			// TODO: handle exception
		}finally{
			threadPool.shutdown();
		}	
	}

通過Java講解ThreadPool線程池的示例
可以看到執行結果。池子中有5個線程,相當于5個工作人員對外提供服務,辦理業務。圖中1號窗口辦理了兩次業務,銀行的受理窗口可以多次被復用。也不一定是每個人辦理兩次,而是誰辦理的快誰就辦理的多。

當我們再線程執行的過程中加400ms的延遲,可以看看效果

public static void main(String[] args) {
		//一池5個受理線程,類似一個銀行5個受理窗口。不管你現在多少個線程,都只有5個
		ExecutorService threadPool=Executors.newFixedThreadPool(5); 
		
		try {
			//模擬有10個顧客過來銀行辦理業務,目前池子里面有5個工作人員提供服務。
			for(int i=1;i<=10;i++){
				//execute方法里面有一個參數,參數類型是Runnable,Runnable是函數式接口,可以用lambda表達式,并且runnable就是這10個顧客
				threadPool.execute(()->{
					System.out.println(Thread.currentThread().getName()+"\t 辦理業務");
				});
				try {
					TimeUnit.MILLISECONDS.sleep(400);
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}finally{
			threadPool.shutdown();
		}	
	}

通過Java講解ThreadPool線程池的示例
此時說明網絡擁堵的情況下或者辦理業務比較慢,則線程池辦理業務任務分配情況比較平均。

2.2.2.newSingleThreadExector

Exectors.newSingleThreadExector()–>一個任務一個任務的執行,一池一線程

public static void main(String[] args) {
	//一池一個工作線程,類似一個銀行有1個受理窗口
	ExecutorService threadPool=Executors.newSingleThreadExecutor(); 	
	try {
		//模擬有10個顧客過來銀行辦理業務
		for(int i=1;i<=10;i++){
			//execute方法里面有一個參數,參數類型是Runnable,Runnable是函數式接口,可以用lambda表達式,并且runnable就是這10個顧客
			threadPool.execute(()->{
				System.out.println(Thread.currentThread().getName()+"\t 辦理業務");
			});
		}
	} catch (Exception e) {
		// TODO: handle exception
	}finally{
		threadPool.shutdown();
	}	}

通過Java講解ThreadPool線程池的示例

2.2.3.newCachedThreadPool

Exectors.newCachedThreadPool()–>執行很多短期異步任務,線程池根據需要創建新線程,但在先前構建的線程可用時將重用他們。可擴容,遇強則強。一池n線程,可擴容,可伸縮,cache緩存的意思
那么池的數量應該設置多少呢,如果銀行只有一個窗口,那么當人來得太多了,就忙不過來。如果銀行有很多個窗口,但是人來的少,此時又顯得浪費資源。那么如何該合理安排呢?這就需要用到newCachedThreadPool()方法,可擴容,可伸縮

public static void main(String[] args) {
		//一池一個工作線程,類似一個銀行有n個受理窗口
		ExecutorService threadPool=Executors.newCachedThreadPool(); 	
		try {
			//模擬有10個顧客過來銀行辦理業務
			for(int i=1;i<=10;i++){
				//execute方法里面有一個參數,參數類型是Runnable,Runnable是函數式接口,可以用lambda表達式,并且runnable就是這10個顧客
				threadPool.execute(()->{
					System.out.println(Thread.currentThread().getName()+"\t 辦理業務");
				});
			}
		} catch (Exception e) {
			// TODO: handle exception
		}finally{
			threadPool.shutdown();
		}	
	}

通過Java講解ThreadPool線程池的示例

public static void main(String[] args) {
		//一池一個工作線程,類似一個銀行有n個受理窗口
		ExecutorService threadPool=Executors.newCachedThreadPool(); 	
		try {
			//模擬有10個顧客過來銀行辦理業務
			for(int i=1;i<=10;i++){
				try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedException e){e.printStackTrace();}
				//execute方法里面有一個參數,參數類型是Runnable,Runnable是函數式接口,可以用lambda表達式,并且runnable就是這10個顧客
				threadPool.execute(()->{
					System.out.println(Thread.currentThread().getName()+"\t 辦理業務");
				});
			}
		} catch (Exception e) {
			// TODO: handle exception
		}finally{
			threadPool.shutdown();
		}	
	}

通過Java講解ThreadPool線程池的示例

3.ThreadPoolExecutor底層原理

newFixedThreadPool底層源代碼

 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

可以看到,底層的參數包含LinkedBlockingQueue阻塞隊列。

newSingleThreadExecutor底層源代碼

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

newCachedThreadPool底層源代碼

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

SynchronousQueue這個阻塞隊列是單一版阻塞隊列,阻塞隊列的容量為1.

這3個方法其實都共同返回了一個對象,即ThreadPoolExecutor的對象

4.線程池7大重要參數

ThreadPoolExecutor的構造函數

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

上面的int corePoolSize,int maximumPoolSize, long keepAliveTime, TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory,
RejectedExecutionHandler handler即我們的七大線程參數
上面是ThreadPoolExecutor類的構造方法,有7大參數:

1)corePoolSize:線程池中的常駐核心線程數,簡稱核心數。
比如說,一個線程池我們可以把它當作銀行的網點,銀行只要開門,就必須至少有一個人在值班,這個就叫常駐核心線程數。比如如果某個銀行周一到周五五個網點全開,那么周一到周五的常駐核心線程數為5.如果今天業務沒有那么頻繁,窗口為1,那么今天的常駐核心線程數就是1

2)maxImumPoolSize:線程池中能夠容納同時執行的最大線程數,此值必須大于等于1

3)keepAliveTime:多余的空閑線程的存活時間,當前池中線程數量超過corePoolSize時,當空閑時間達到keepAliveTime時,多余線程會被銷毀直到剩下corePoolSize為止
如果線程池中有常駐線程數,又有最大線程數,說明平時是用常駐的,工作緊張了,它會擴容到最大線程數,如果業務降下來了,我們設置了多余的空閑線程的存活時間,比如設置30s,如果30s都沒有多余的請求過來,有些銀行就會關閉窗口,所以它不僅會擴大還會縮小。

4)unit:keepAliveTime的單位
單位:是秒,毫秒,微秒。

5)workQueue:任務隊列,被提交但尚未被執行的任務
這是一個阻塞隊列,比如說銀行,只有3個受理窗口,而來了4個客戶。這個阻塞隊列就是銀行的候客區,來了客戶不能讓他走了。窗口數控制了線程的并發數。

6)threadFactory:表示生成線程池中工作線程的線程工廠,用于創建線程,一般默認即可
線程都是統一的創建。線程池里面有已經new好的線程,這些由線程池工廠生產。

7)handler:拒絕策略,表示當前隊列滿了,并且工作線程大于等于線程池的最大線程數(maximumPoolSize)時如何來拒絕請求執行的runnable的策略

比如說今天銀行客流高峰,三個窗口都滿了,候客區也滿了。我們沒有選擇繼續拉人,因為不安全我們選擇委婉的拒絕。

以上就是關于“通過Java講解ThreadPool線程池的示例”的內容,如果改文章對你有所幫助并覺得寫得不錯,勞請分享給你的好友一起學習新知識,若想了解更多相關知識內容,請多多關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

柘荣县| 新闻| 浦江县| 苗栗县| 辽源市| 巴彦县| 从化市| 上栗县| 武威市| 佛山市| 左贡县| 桐梓县| 望江县| 道孚县| 巴彦淖尔市| 奉节县| 忻州市| 沭阳县| 祁门县| 大埔县| 云南省| 玉溪市| 施秉县| 吉木乃县| 杂多县| 札达县| 西安市| 横山县| 弥渡县| 义乌市| 日喀则市| 郸城县| 塔河县| 洛浦县| 太和县| 肥乡县| 盐津县| 松溪县| 巍山| 胶南市| 鄂温|