亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java多線程中的Executor框架解析

 更新時(shí)間:2023年12月13日 09:17:03   作者:得過(guò)且過(guò)的勇者y  
這篇文章主要介紹了Java多線程中的Executor框架解析,Executor 框架是 Java5 之后引進(jìn)的,在 Java 5 之后,通過(guò) Executor 來(lái)啟動(dòng)線程比使用 Thread 的 start 方法更好,除了更易管理,效率更好,需要的朋友可以參考下

前言

Executor 框架是 Java5 之后引進(jìn)的,在 Java 5 之后,通過(guò) Executor 來(lái)啟動(dòng)線程比使用 Thread 的 start 方法更好,除了更易管理,效率更好(用線程池實(shí)現(xiàn),節(jié)約開(kāi)銷)。

Executor 框架不僅包括了線程池的管理,還提供了線程工廠、隊(duì)列以及拒絕策略等,Executor 框架讓并發(fā)編程變得更加簡(jiǎn)單。

Executor框架的組成:

  • 任務(wù)(Runnable/Callable):任務(wù)通過(guò)Runnable接口或Callable接口進(jìn)行定義。Runnable接口或Callable接口實(shí)現(xiàn)類都可以被 ThreadPoolExecutor執(zhí)行
  • 任務(wù)的執(zhí)行(Executor):任務(wù)執(zhí)行機(jī)制的核心接口 Executor,以及繼承自Executor接口的ExecutorService接口。ThreadPoolExecutor實(shí)現(xiàn)了ExecutorService接口
  • 異步的計(jì)算結(jié)果(Future):Future接口以及Future接口的實(shí)現(xiàn)類FutureTask類都可以代表異步計(jì)算的結(jié)果。當(dāng)我們把Runnable接口或Callable接口的實(shí)現(xiàn)類提交給ThreadPoolExecutor執(zhí)行后就會(huì)返回一個(gè)Future對(duì)象

一、Executor接口

線程池簡(jiǎn)化了線程的管理工作, 并且JUC提供了一種靈活的線程池實(shí)現(xiàn)來(lái)作為Executor框架的一部分。

在Java類庫(kù)中,任務(wù)執(zhí)行的主要抽象不是Thread而是Executor,Executor只定義了execute一個(gè)方法,是最頂層的接口。

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);

execute方法接受一個(gè)Runnable參數(shù),這個(gè)方法定義為在未來(lái)的某個(gè)時(shí)間執(zhí)行傳入的方法,方法的運(yùn)行可以在一個(gè)新的線程,在線程池或者在調(diào)用的線程中,該方法無(wú)法接收到線程的執(zhí)行結(jié)果(當(dāng)然Runnable接口本身也沒(méi)有返回值)。

雖然Executor是個(gè)簡(jiǎn)單的接口,但它卻為靈活且強(qiáng)大的異步任務(wù)執(zhí)行框架提供了基礎(chǔ),該框架能支持多種不同類型的任務(wù)執(zhí)行策略。它提供了一種標(biāo)準(zhǔn)的方法將任務(wù)的提交過(guò)程與執(zhí)行過(guò)程解耦開(kāi)來(lái),并用Runnable來(lái)表示任務(wù)。

Executor的實(shí)現(xiàn)還提供了對(duì)生命周期的支持,以及統(tǒng)計(jì)信息收集、應(yīng)用程序管理機(jī)制和性能監(jiān)視等機(jī)制。

**Executor基于生產(chǎn)者-消費(fèi)者模式,提交任務(wù)的操作相當(dāng)于生產(chǎn)者,執(zhí)行任務(wù)的線程相當(dāng)于消費(fèi)者。**如果要在程序中實(shí)現(xiàn)一個(gè)生產(chǎn)者-消費(fèi)者的設(shè)計(jì),那么最簡(jiǎn)單的方式就是使用Executor。

二、ExecutorService接口

Executor框架使用Runnable作為其基本的任務(wù)表示形式。Runnable是一種有很大局限的抽象,它的run方法執(zhí)行任務(wù)后不能返回一個(gè)值或者拋出一個(gè)受檢查的異常。許多任務(wù)實(shí)際上都是存在延遲的計(jì)算——執(zhí)行數(shù)據(jù)庫(kù)查詢,從網(wǎng)絡(luò)上獲取資源,或者計(jì)算某個(gè)復(fù)雜的功能。對(duì)于這些任務(wù),Callable是一種更好的抽象,它認(rèn)為主入口點(diǎn)(call)將返回一個(gè)值,并可能拋出一個(gè)異常。

因此引入了ExecutorService,它繼承自Executor,并且在其基礎(chǔ)上增加了很多功能,可以生成用于跟蹤一個(gè)或多個(gè)異步任務(wù)進(jìn)度的Future的方法,以解決Executor的局限性。

Future表示一個(gè)任務(wù)的生命周期,并且提供了響應(yīng)的方法來(lái)判斷是否已經(jīng)完成或取消,以及獲取任務(wù)的結(jié)果和取消任務(wù)等。

在Future規(guī)范中包含的隱含意義是任務(wù)的生命周期只能前進(jìn),不能后退,就像ExecutorService的生命周期一樣。當(dāng)某個(gè)任務(wù)完成后,它就永遠(yuǎn)停留在完成狀態(tài)。

get方法的行為取決于任務(wù)的狀態(tài)(尚未開(kāi)始、正在運(yùn)行、已完成)。如果任務(wù)已完成那么get會(huì)立即返回或者拋出一個(gè)Exception,如果任務(wù)沒(méi)有完成,那么get將阻塞并直到任務(wù)完成。如果任務(wù)拋出了一場(chǎng),那么get將該異常封裝為ExecutionException并重新拋出。如果任務(wù)被取消,那么get將拋出CancellationException。如果get拋出了ExecutionException,那么可以通過(guò)getCause來(lái)獲得被封裝的初始異常。

定義了以下方法:

  • void shutdown():?jiǎn)?dòng)有序關(guān)機(jī),其中執(zhí)行先前提交的任務(wù),但不接受新任務(wù)。如果調(diào)用已經(jīng)關(guān)閉,則沒(méi)有額外的效果。不會(huì)阻塞等待先前提交的任務(wù)執(zhí)行完成
  • List<Runnable> shutdownNow():嘗試停止所有正在執(zhí)行的任務(wù),停止對(duì)等待任務(wù)的處理,并返回等待執(zhí)行的任務(wù)列表。不會(huì)阻塞等待正在執(zhí)行的任務(wù)終止只是盡最大努力停止處理正在執(zhí)行的任務(wù)之外,沒(méi)有任何保證。例如,典型的實(shí)現(xiàn)將通過(guò)Thread.interrupt取消,因此任何未能響應(yīng)中斷的任務(wù)可能永遠(yuǎn)不會(huì)終止
  • boolean isShutdown():如果此執(zhí)行器已關(guān)閉(調(diào)用了關(guān)閉方法),則返回true
  • boolean isTerminated():如果關(guān)閉后所有任務(wù)都已完成,則返回true。注意,除非先調(diào)用shutdown或shutdownNow,否則isTerminated永遠(yuǎn)不會(huì)為真
  • boolean awaitTermination(long timeout, TimeUnit unit):阻塞直到所有任務(wù)在關(guān)機(jī)請(qǐng)求后完成執(zhí)行,或者超時(shí)發(fā)生,或者當(dāng)前線程被中斷,以先發(fā)生的為準(zhǔn)
  • <T> Future<T> submit(Callablet task):提交一個(gè)帶返回值的任務(wù)以供執(zhí)行,并返回表示該任務(wù)的掛起結(jié)果的Future。Future的get方法將在成功完成任務(wù)時(shí)返回任務(wù)的結(jié)果
  • <T> Future<T> submit(Runnable task, T result):提交可運(yùn)行任務(wù)以供執(zhí)行,并返回表示該任務(wù)的Future。Future的get方法將在成功完成時(shí)返回給定的結(jié)果
  • Future<?> submit(Runnable task):提交可運(yùn)行任務(wù)以供執(zhí)行,并返回表示該任務(wù)的Future。Future的get方法將在成功完成時(shí)返回null
  • <T> Listfuture<t> invokeAll(Collection? extends Callable<T> tasks):執(zhí)行給定的任務(wù),并在所有任務(wù)完成時(shí)返回保存其狀態(tài)和結(jié)果的future列表。每個(gè)Future對(duì)象的isDone方法都會(huì)返回true。請(qǐng)注意,已完成的任務(wù)可以正常終止,也可以拋出異常終止。如果在執(zhí)行此操作時(shí)修改了給定的集合,則此方法的結(jié)果是未定義的
  • <T> T invokeAny(Collection? extends Callable<T> tasks):執(zhí)行給定的任務(wù),如果有成功完成的任務(wù),則返回成功完成的任務(wù)的結(jié)果(即不拋出異常)。在正?;虍惓7祷貢r(shí),未完成的任務(wù)將被取消。如果在執(zhí)行此操作時(shí)修改了給定的集合,則此方法的結(jié)果是未定義的。

三、ThreadPoolExecutor類

ThreadPoolExecutor實(shí)現(xiàn)了ExecutorService(實(shí)際上是繼承了AbstractExecutorService),為了在廣泛的上下文中發(fā)揮作用,該類提供了許多可調(diào)參數(shù)和可擴(kuò)展性掛鉤:

  • corePoolSize:指定了線程池中的線程數(shù)量,它的數(shù)量決定了添加的任務(wù)是開(kāi)辟新的線程去執(zhí)行,還是放到workQueue任務(wù)隊(duì)列中去
  • maximumPoolSize:指定了線程池中的最大線程數(shù)量,這個(gè)參數(shù)會(huì)根據(jù)你使用的workQueue任務(wù)隊(duì)列的類型,決定線程池會(huì)開(kāi)辟的最大線程數(shù)量
  • keepAliveTime:當(dāng)線程池中空閑線程數(shù)量超過(guò)corePoolSize時(shí),多余的線程(救急線程)會(huì)在多長(zhǎng)時(shí)間內(nèi)被銷毀
  • unit:keepAliveTime的單位
  • workQueue:任務(wù)隊(duì)列,被添加到線程池中,但尚未被執(zhí)行的任務(wù);它一般分為直接提交隊(duì)列、有界任務(wù)隊(duì)列、無(wú)界任務(wù)隊(duì)列、優(yōu)先任務(wù)隊(duì)列幾種
  • threadFactory:線程工廠,用于創(chuàng)建線程,一般用默認(rèn)即可
  • handler:拒絕策略;當(dāng)任務(wù)太多來(lái)不及處理時(shí),如何拒絕任務(wù)

1、狀態(tài)

  1. RUNNING(-1<<29):接受新任務(wù)并且處理排隊(duì)任務(wù)
  2. SHUTDOWN(0<<29):不接受新任務(wù)但是處理排隊(duì)任務(wù)
  3. STOP(1<<29):不接受新任務(wù)也不處理排隊(duì)任務(wù),同時(shí)中斷處理中的任務(wù)
  4. TYDING(2<<29):所有任務(wù)被終止,工作線程數(shù)為0之后進(jìn)入該狀態(tài),并且會(huì)執(zhí)行terminated()鉤子函數(shù)
  5. TERMINATED(3<<29):terminated()鉤子函數(shù)執(zhí)行完畢后

狀態(tài)單調(diào)地隨時(shí)間增加,但不需要達(dá)到每個(gè)狀態(tài)。

  • RUNNING->SHUTDOWN:調(diào)用shutdown()
  • RUNNING/SHUTDOWN->STOP:調(diào)用shutdownNow()
  • STOP->TYDING:當(dāng)隊(duì)列和池都為空時(shí)
  • TIDYING -> TERMINATED:terminated()鉤子函數(shù)執(zhí)行完畢后

ThreadPoolExecutor中對(duì)于狀態(tài)的記錄保存在一個(gè)AtomicInteger類型的變量中,其中高三位就是用于記錄線程池的狀態(tài),而低的29位用于記錄線程數(shù)量。

2、Worker

ThreadPoolExecutor中定義了一個(gè)私有靜態(tài)類Worker,其繼承自AbstractQueuedSynchronizer類,并實(shí)現(xiàn)了Runnable接口。其中維護(hù)了線程實(shí)例(Thread)、任務(wù)實(shí)例(Runnable)、線程任務(wù)計(jì)數(shù)器(long)變量。

這個(gè)類適當(dāng)?shù)財(cái)U(kuò)展了AbstractQueuedSynchronizer,以簡(jiǎn)化獲取和釋放圍繞每個(gè)任務(wù)執(zhí)行的鎖。這可以防止中斷,這些中斷旨在喚醒等待任務(wù)的工作線程,而不是中斷正在運(yùn)行的任務(wù)。我們實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的不可重入互斥鎖,而不是使用ReentrantLock,因?yàn)槲覀儾幌Mぷ魅蝿?wù)在調(diào)用setCorePoolSize等池控制方法時(shí)能夠重新獲得鎖。此外,為了在線程實(shí)際開(kāi)始運(yùn)行任務(wù)之前抑制中斷,我們將鎖狀態(tài)初始化為負(fù)值,并在啟動(dòng)時(shí)(在runWorker中)清除它。

3、擴(kuò)展

該類還定義了三個(gè)protected類型的鉤子函數(shù):

  • beforeExecute:線程池任務(wù)運(yùn)行前執(zhí)行
  • afterExecute:線程池任務(wù)運(yùn)行后執(zhí)行
  • terminated:線程池退出后執(zhí)行

這幾個(gè)方法在ThreadPoolExecutor中為空實(shí)現(xiàn)。

四、ForkJoinPool類

Fork/Join框架是Java7提供的一個(gè)用于并行執(zhí)行任務(wù)的框架,是一個(gè)把大任務(wù)分割成若干個(gè)小任務(wù),最終匯總每個(gè)小任務(wù)結(jié)果后得到大任務(wù)結(jié)果的框架

Fork就是把一個(gè)大任務(wù)切分為若干個(gè)子任務(wù)并行的執(zhí)行,Join就是合并這些子任務(wù)的執(zhí)行結(jié)果,最后得到這個(gè)大任務(wù)的結(jié)果。比如計(jì)算1+2+…+10000,可以分割成10個(gè)子任務(wù),每個(gè)子任務(wù)分別對(duì)1000個(gè)數(shù)進(jìn)行求和,最終匯總這10個(gè)子任務(wù)的結(jié)果。

1、工作竊取算法

ForkJoinPool是運(yùn)行ForkJoinTasks的ExecutorService。**ForkJoinPool與其他類型的ExecutorService的區(qū)別主要在于使用了工作竊取。工作竊取算法是指某個(gè)線程從其他隊(duì)列里竊取任務(wù)來(lái)執(zhí)行。**那么為什么要使用工作竊取算法呢?**假如我們需要做一個(gè)比較大的任務(wù),可以把這個(gè)任務(wù)分割為若干個(gè)互不干擾的子任務(wù),為了減少線程間的競(jìng)爭(zhēng),把這些子任務(wù)分別放到不同的隊(duì)列里,并為每個(gè)隊(duì)列創(chuàng)建一個(gè)單獨(dú)的線程來(lái)執(zhí)行隊(duì)列里的任務(wù),線程和隊(duì)列一一對(duì)應(yīng)。**比如A線程負(fù)責(zé)處理A隊(duì)列里的任務(wù)。但是有的線程會(huì)先把自己隊(duì)列里的任務(wù)干完,而其他線程對(duì)應(yīng)的隊(duì)列里還有任務(wù)等待處理。干完活的線程與其等著,不如去幫其他線程干活,于是它就去其他線程的隊(duì)列里竊取一個(gè)任務(wù)來(lái)執(zhí)行。而這時(shí)它們會(huì)訪問(wèn)同一個(gè)隊(duì)列,所以為了減少竊取任務(wù)線程之間的競(jìng)爭(zhēng),通常會(huì)使用雙端隊(duì)列,被竊取任務(wù)線程永遠(yuǎn)從雙端隊(duì)列的頭部拿任務(wù),而竊取任務(wù)的線程永遠(yuǎn)從雙端隊(duì)列的尾部拿任務(wù)執(zhí)行。

工作竊取算法的優(yōu)點(diǎn):充分利用線程進(jìn)行并行計(jì)算,減少了線程間的競(jìng)爭(zhēng)

工作竊取算法的缺點(diǎn):在某些情況下還是存在競(jìng)爭(zhēng),比如雙端隊(duì)列里只有一個(gè)任務(wù)時(shí)。并且該算法會(huì)消耗了更多的系統(tǒng)資源,比如創(chuàng)建多個(gè)線程和多個(gè)雙端隊(duì)列。

2、Fork/Join的設(shè)計(jì)

想要設(shè)計(jì)一個(gè)Fork/Join框架,需要完成兩個(gè)步驟:

  • 分割任務(wù):需要有一個(gè)fork類來(lái)把大任務(wù)分割成子任務(wù),有可能子任務(wù)還是很大,所以還需要不停地分割,直到分割出的子任務(wù)足夠小
  • 執(zhí)行任務(wù)并合并結(jié)果:分割的子任務(wù)分別放在雙端隊(duì)列里,然后幾個(gè)啟動(dòng)線程分別從雙端隊(duì)列里獲取任務(wù)執(zhí)行。子任務(wù)執(zhí)行完的結(jié)果都統(tǒng)一放在一個(gè)隊(duì)列里,啟動(dòng)一個(gè)線程從隊(duì)列里拿數(shù)據(jù),然后合并這些數(shù)據(jù)。

Fork/Join使用兩個(gè)類來(lái)完成以上兩件事情:

  • ForkJoinTask(抽象類):我們要使用ForkJoin框架,必須首先創(chuàng)建一個(gè)ForkJoin任務(wù)。它提供在任務(wù)中執(zhí)行fork()和join()操作的機(jī)制。通常情況下我們不需要直接繼承ForkJoinTask類,只需要繼承它的子類,F(xiàn)ork/Join框架提供了以下兩個(gè)子類:
    • RecursiveAction(抽象類):用于沒(méi)有返回結(jié)果的任務(wù)
    • RecursiveTask(抽象類):用于有返回結(jié)果的任務(wù)
  • ForkJoinPool:ForkJoinTask需要通過(guò)ForkJoinPool來(lái)執(zhí)行

任務(wù)分割出的子任務(wù)會(huì)添加到當(dāng)前工作線程所維護(hù)的雙端隊(duì)列中,進(jìn)入隊(duì)列的頭部。當(dāng)一個(gè)工作線程的隊(duì)列里暫時(shí)沒(méi)有任務(wù)時(shí),它會(huì)隨機(jī)從其他工作線程的隊(duì)列的尾部獲取一個(gè)線程。

public class CountTask extends RecursiveTask<Integer> {
	private int start;
	private int end;
	public CountTask(int start, int end) {
		this.start = start;
		this.end = end;
	}
	@Override
	protected Integer compute() {
		int sum = 0;
		// 如果任務(wù)足夠小就計(jì)算任務(wù)
		boolean canCompute = (end - start) <= THRESHOLD;
		if (canCompute) {
			for (int i = start; i <= end; i++) {
				sum += i;
			}
		} else {
			// 如果任務(wù)大于閾值,就分裂成兩個(gè)子任務(wù)計(jì)算
			int middle = (start + end) / 2;
			CountTask leftTask = new CountTask(start, middle);
			CountTask rightTask = new CountTask(middle + 1, end);
			// 執(zhí)行子任務(wù)
			leftTask.fork();
			rightTask.fork();
			// 等待子任務(wù)執(zhí)行完,并得到其結(jié)果
			int leftResult = leftTask.join();
			int rightResult = rightTask.join();
			// 合并子任務(wù)
			sum = leftResult + rightResult;
		}
		return sum;
	}
	public static void main(String[] args) {
		ForkJoinPool forkJoinPool = new ForkJoinPool();
		CountTask task = new CountTask(1, 4);
		// 執(zhí)行一個(gè)任務(wù)
		Future<Integer> result = forkJoinPool.submit(task);
		try {
			System.out.println(result.get());
		} catch (InterruptedException e) {
		} catch (ExecutionException e) {
		}
	}
}

RecursiveTask需要實(shí)現(xiàn)compute方法,在這個(gè)方法里,首先需要判斷任務(wù)是否足夠小,如果足夠小就直接執(zhí)行任務(wù)。如果不足夠小就必須分割成兩個(gè)子任務(wù),每個(gè)子任務(wù)在調(diào)用fork方法時(shí)又會(huì)進(jìn)入compute方法。最后使用join方法等待子任務(wù)執(zhí)行完成并得到其結(jié)果。

ForkJoinTask在執(zhí)行的時(shí)候可能會(huì)拋出異常,但是我們沒(méi)辦法在主線程里直接捕獲異常,所以ForkJoinTask提供了isCompletedAbnormally()方法來(lái)檢查任務(wù)是否已經(jīng)拋出異?;蛞呀?jīng)被取消了,并且可以通過(guò)ForkJoinTask的getException方法來(lái)獲取異常。

getException方法返回Throwable對(duì)象,如果任務(wù)被取消了則返回CancellationException,如果任務(wù)沒(méi)有完成或者沒(méi)有拋出異常則返回null。

3、執(zhí)行原理

ForkJoinPool由ForkJoinTask數(shù)組和ForkJoinWorkerThread數(shù)組組成,F(xiàn)orkJoinTask數(shù)組負(fù)責(zé)存放程序提交給ForkJoinPool的任務(wù),而ForkJoinWorkerThread數(shù)組負(fù)責(zé)執(zhí)行這些任務(wù)。

當(dāng)我們調(diào)用ForkJoinTask的fork方法時(shí),程序會(huì)調(diào)用ForkJoinWorkerThread的pushTask方法異步地執(zhí)行這個(gè)任務(wù),然后立即返回結(jié)果。

pushTask方法把當(dāng)前任務(wù)存放在ForkJoinTask數(shù)組隊(duì)列里,然后再調(diào)用ForkJoinPool的signalWork反復(fù)噶喚醒或創(chuàng)建一個(gè)工作線程來(lái)執(zhí)行任務(wù)。

五、ScheduledThreadPool類

ScheduledThreadPoolExecutor主要用來(lái)在給定的延遲后運(yùn)行任務(wù),或者定期執(zhí)行任務(wù)。ScheduledThreadPoolExecutor使用任務(wù)隊(duì)列DelayQueue封裝了一個(gè)PriorityQueue,PriorityQueue會(huì)對(duì)隊(duì)列中的任務(wù)進(jìn)行排序,執(zhí)行所需時(shí)間短的放在前面先被執(zhí)行(ScheduledFutureTask的time變量小的先執(zhí)行),如果執(zhí)行所需時(shí)間相同則先提交的任務(wù)將被先執(zhí)行(ScheduledFutureTask的squenceNumber變量小的先執(zhí)行)。

1、ScheduledExecutorService

ScheduledThreadPool類繼承自ThreadPoolExecutor,并且實(shí)現(xiàn)了ScheduledExecutorService接口。

ScheduledExecutorService接口定義了幾個(gè)方法:

  1. ScheduleFuture<?> schedule(Runnable command, long delay, TimeUnit unit):提交在給定延遲后啟用的一次性任務(wù)
  2. ScheduleFuture schedule(Callable command, long delay, TimeUnit unit):提交在給定延遲之后啟用的帶返回值的一次性任務(wù)
  3. ScheduleFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit):提交一個(gè)周期性任務(wù),任務(wù)開(kāi)始時(shí)進(jìn)行計(jì)時(shí)(如果任務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng)甚至超過(guò)period時(shí)間,會(huì)導(dǎo)致任務(wù)連續(xù)執(zhí)行)
  4. ScheduleFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit):提交一個(gè)周期性任務(wù),任務(wù)執(zhí)行完成之后才進(jìn)行計(jì)時(shí)

ScheduledFuture繼承自Delayed接口和Future接口,自己本身沒(méi)有定義新的方法。

Delayed接口是一個(gè)混合風(fēng)格的接口,用于標(biāo)記應(yīng)該在給定延遲后執(zhí)行的對(duì)象。這個(gè)接口定義了一個(gè)getDelay方法,用于返回剩余的延遲時(shí)間。此外這個(gè)接口繼承了Comparable接口,意味著此接口的實(shí)現(xiàn)必須定義一個(gè)compareTo方法,該方法提供與其getDelay方法一致的排序

2、比較Timer

Timer對(duì)系統(tǒng)時(shí)鐘的變化敏感,ScheduledThreadPoolExecutor不是

Timer只有一個(gè)執(zhí)行線程,因此長(zhǎng)時(shí)間運(yùn)行的任務(wù)可以延遲其他任務(wù)。 ScheduledThreadPoolExecutor可以配置任意數(shù)量的線程。 此外,如果你想(通過(guò)提供 ThreadFactory),你可以完全控制創(chuàng)建的線程

在TimerTask中拋出的運(yùn)行時(shí)異常會(huì)殺死一個(gè)線程,從而導(dǎo)致 Timer 死機(jī),即計(jì)劃任務(wù)將不再運(yùn)行。ScheduledThreadExecutor不僅捕獲運(yùn)行時(shí)異常,還允許您在需要時(shí)處理它們(通過(guò)重寫(xiě)afterExecute方法ThreadPoolExecutor)。拋出異常的任務(wù)將被取消,但其他任務(wù)將繼續(xù)運(yùn)行

六、Executors類

Executors是Java中用于創(chuàng)建線程池的工廠類,它提供了一系列的靜態(tài)工廠方法,用于創(chuàng)建不同類型的線程池。這些工廠方法隱藏了線程池的復(fù)雜性,使得線程池的創(chuàng)建變得非常簡(jiǎn)單。Executors工廠類提供的線程池有以下幾種類型:

  • newCachedThreadPool():CachedThreadPool的corePoolSize 被設(shè)置為0,maximumPoolSize被設(shè)置為Integer.MAX.VALUE,即它是無(wú)界的,這也就意味著如果主線程提交任務(wù)的速度高于maximumPool中線程處理任務(wù)的速度時(shí),CachedThreadPool會(huì)不斷創(chuàng)建新的線程。極端情況下,這樣會(huì)導(dǎo)致耗盡 cpu和內(nèi)存資源
  • newFixedThreadPool(int nThreads):創(chuàng)建一個(gè)固定大小的線程池,其中包含指定數(shù)量的線程。線程數(shù)量是固定的,不會(huì)自動(dòng)擴(kuò)展,即沒(méi)有救急線程
  • newSingleThreadExecutor():創(chuàng)建一個(gè)單線程的線程池。這個(gè)線程池中只包含一個(gè)線程,用于串行執(zhí)行任務(wù)。適用于需要按順序執(zhí)行任務(wù)的場(chǎng)景
  • newScheduledThreadPool(int corePoolSize):創(chuàng)建一個(gè)固定大小的線程池,用于定時(shí)執(zhí)行任務(wù)。線程數(shù)量固定,不會(huì)自動(dòng)擴(kuò)展。適用于定時(shí)執(zhí)行任務(wù)的場(chǎng)景
  • newSingleThreadScheduledExecutor():創(chuàng)建一個(gè)單線程的定時(shí)執(zhí)行線程池。只包含一個(gè)線程,用于串行定時(shí)執(zhí)行任務(wù)
  • newWorkStealingPool(int parallelism):該線程池維護(hù)足夠的線程以支持給定的并行級(jí)別,并且可以使用多個(gè)隊(duì)列來(lái)減少爭(zhēng)用。并行性級(jí)別對(duì)應(yīng)于積極參與或可用參與任務(wù)處理的最大線程數(shù)。實(shí)際的線程數(shù)可以動(dòng)態(tài)地增加和減少。工作竊取池不能保證所提交任務(wù)的執(zhí)行順序

除此之外還提供了創(chuàng)建ThreadFactory實(shí)例,將Runnable實(shí)例轉(zhuǎn)換為Callable實(shí)例等方法。

到此這篇關(guān)于Java多線程中的Executor框架解析的文章就介紹到這了,更多相關(guān)Java的Executor框架內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • spring?NamedContextFactory在Fegin配置及使用詳解

    spring?NamedContextFactory在Fegin配置及使用詳解

    在我們?nèi)粘m?xiàng)目中,使用FeignClient實(shí)現(xiàn)各系統(tǒng)接口調(diào)用變得更加簡(jiǎn)單,?在各個(gè)系統(tǒng)集成過(guò)程中,難免會(huì)遇到某些系統(tǒng)的Client需要特殊的配置、返回讀取等需求。Feign使用NamedContextFactory來(lái)為每個(gè)Client模塊構(gòu)造單獨(dú)的上下文(ApplicationContext)
    2023-11-11
  • springboot如何根據(jù)不同的日志級(jí)別顯示不同的顏色

    springboot如何根據(jù)不同的日志級(jí)別顯示不同的顏色

    這篇文章主要介紹了springboot如何根據(jù)不同的日志級(jí)別顯示不同的顏色問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Mybatis-plus使用注解 @TableField(exist = false)

    Mybatis-plus使用注解 @TableField(exist = false)

    這篇文章主要介紹了Mybatis-plus使用注解 @TableField(exist = false),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • mybatis關(guān)聯(lián)關(guān)系映射的實(shí)現(xiàn)

    mybatis關(guān)聯(lián)關(guān)系映射的實(shí)現(xiàn)

    MyBatis的關(guān)聯(lián)關(guān)系映射在復(fù)雜數(shù)據(jù)模型中至關(guān)重要,使開(kāi)發(fā)人員能夠以最靈活的方式滿足不同項(xiàng)目的需求,本文就來(lái)介紹一下mybatis關(guān)聯(lián)關(guān)系映射的實(shí)現(xiàn),感興趣的可以了解一下
    2023-09-09
  • Java實(shí)現(xiàn)解析并生成xml原理實(shí)例詳解

    Java實(shí)現(xiàn)解析并生成xml原理實(shí)例詳解

    這篇文章主要介紹了Java實(shí)現(xiàn)解析并生成xml原理實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Java中WeakHashMap和HashMap的區(qū)別詳解

    Java中WeakHashMap和HashMap的區(qū)別詳解

    這篇文章主要介紹了Java中WeakHashMap和HashMap的區(qū)別詳解,WeakHashMap和HashMap一樣,WeakHashMap也是一個(gè)散列表,它存儲(chǔ)的內(nèi)容也是鍵值對(duì)(key-value)映射,而且鍵和值都可以為null,需要的朋友可以參考下
    2023-09-09
  • java selenium 常見(jiàn)web UI 元素操作及API使用

    java selenium 常見(jiàn)web UI 元素操作及API使用

    本文主要介紹java selenium 常見(jiàn)web UI 元素操作,這里幫大家整理了相關(guān)資料并附示例代碼,有需要的小伙伴可以參考下
    2016-08-08
  • Java系統(tǒng)的高并發(fā)解決方法詳解

    Java系統(tǒng)的高并發(fā)解決方法詳解

    這篇文章主要介紹了Java系統(tǒng)的高并發(fā)解決方法,內(nèi)容十分豐富,在這里分享給大家,需要的朋友可以參考。
    2017-09-09
  • 使用Swagger2實(shí)現(xiàn)自動(dòng)生成RESTful?API文檔

    使用Swagger2實(shí)現(xiàn)自動(dòng)生成RESTful?API文檔

    在開(kāi)發(fā)?RESTful?API?的過(guò)程中,文檔是非常重要的一部分,可以幫助開(kāi)發(fā)者了解?API?的功能和使用方法,本文將使用Swagger2?實(shí)現(xiàn)自動(dòng)生成?RESTful?API?文檔,需要的可以參考一下
    2023-06-06
  • 淺談Java中的重載,重寫(xiě),多態(tài),靜態(tài)綁定、動(dòng)態(tài)綁定

    淺談Java中的重載,重寫(xiě),多態(tài),靜態(tài)綁定、動(dòng)態(tài)綁定

    這篇文章主要介紹了淺談Java中的重載,重寫(xiě),多態(tài),靜態(tài)綁定、動(dòng)態(tài)綁定,具有一定借鑒價(jià)值
    2018-01-01

最新評(píng)論