最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 線程創(chuàng)建方式全過程

 更新時(shí)間:2026年05月15日 09:44:23   作者:大大杰哥  
本文介紹了繼承Thread類、實(shí)現(xiàn)Runnable接口和Callable接口創(chuàng)建線程的方法,以及線程池的使用理邏輯和任務(wù)處理機(jī)制,并重點(diǎn)講解了線程池參數(shù)配置、常用阻塞隊(duì)列和拒絕策略、線程池的優(yōu)勢和應(yīng)用場景、虛擬線程的特點(diǎn)和創(chuàng)建方法、ScheduledThreadPool線程池原理和使用方法

1、繼承Thread類

特點(diǎn):

1、編程簡單直觀
直接在類中編寫線程邏輯
適合簡單的線程場景

2、受單繼承限制,不利于資源共享,耦合度高,不適合線程池

類代碼:

public class ThreadExtend extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("線程執(zhí)行:" + Thread.currentThread().getName());
        }
    }
}

主程序代碼:

public class main {
    public static void main(String[] args) {
            ThreadExtend thread1=new ThreadExtend();
            thread1.start();
            ThreadExtend thread2=new ThreadExtend();
            thread2.start();
    }
}
//結(jié)果
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0

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

特點(diǎn):

1、避免單繼承局限
Java 是單繼承語言,實(shí)現(xiàn) Runnable 后還可以繼承其他類
更靈活,符合面向?qū)ο蟮脑O(shè)計(jì)原則

2、適合資源共享
多個(gè)線程可以共享同一個(gè) Runnable 實(shí)例
適合多個(gè)線程處理同一資源的場景

3、便于線程池管理
線程池主要接受 Runnable/Callable 任務(wù)
更容易與現(xiàn)代并發(fā)工具集成

4、代碼解耦
將任務(wù)邏輯與線程控制分離
更符合"組合優(yōu)于繼承"的設(shè)計(jì)原則

類代碼:

//演示共享資源
public class ThreadRunnable implements Runnable{
    private int nums=20;
    @Override
    public void run() {
        while(nums>0) {
            System.out.println("線程執(zhí)行:" + Thread.currentThread().getName());
            nums--;
        }
    }
}

主程序代碼:

public class main {
    public static void main(String[] args) {
            ThreadRunnable threadRunnable = new ThreadRunnable();
        Thread t1=new Thread(threadRunnable,"線程1");
        Thread t2=new Thread(threadRunnable,"線程2");
        Thread t3=new Thread(threadRunnable,"線程3");
        t1.start();
        t2.start();
        t3.start();
    }
}
//示例結(jié)果出現(xiàn)了線程安全問題,輸出大于20個(gè),可以在while循環(huán)內(nèi)加鎖
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程3
線程執(zhí)行:線程2
線程執(zhí)行:線程2
線程執(zhí)行:線程2
線程執(zhí)行:線程1
線程執(zhí)行:線程3

3、實(shí)現(xiàn)Callable接口

特點(diǎn):

1、

需要重寫call()方法,有返回值,可以通過FutureTask獲取狀態(tài)。

FutureTask常用方法

(1)get()-阻塞獲取結(jié)果

String result = futureTask.get(); // 一直等待直到任務(wù)完成

(2)get(long timeout, TimeUnit unit) - 超時(shí)獲取

// 最多等待5秒,超時(shí)拋 TimeoutException
String result = futureTask.get(5, TimeUnit.SECONDS);

(3)isDone() - 是否完成

boolean done = futureTask.isDone();
// true: 任務(wù)已完成(正常完成、異?;蛉∠?
// false: 任務(wù)還在執(zhí)行中

(4)isCancelled() - 是否被取消

boolean cancelled = futureTask.isCancelled();
// true: 任務(wù)在正常完成前被取消
// false: 任務(wù)未被取消

(5)cancel(boolean mayInterruptIfRunning) - 取消任務(wù)

boolean cancelled = futureTask.cancel(false);
// false: 不中斷正在運(yùn)行的任務(wù),只阻止未開始的任務(wù)
// true: 嘗試中斷正在運(yùn)行的任務(wù)
// 返回值:
// true: 取消成功
// false: 取消失?。ㄈ蝿?wù)已完成或已被取消)

cancel(false)在線程還在線程池排隊(duì)沒運(yùn)行的時(shí)候能停下來

cancel(true)需要在run()代碼中判斷Thread.currentThread().isInterrupted(),檢測線程是否收到中斷信號來手動中斷?;蛘邎?zhí)行sleep()等響應(yīng)中斷的阻塞方法也會使得任務(wù)退出。

(6)run() - 執(zhí)行任務(wù)

futureTask.run(); // 通常在 Thread 中調(diào)用
// new Thread(futureTask).start(); 內(nèi)部會調(diào)用這個(gè)方法

Thread.start()調(diào)用第二次會直接報(bào)錯(cuò)拋出異常。

FutureTask.run()調(diào)用第二次不會報(bào)錯(cuò)但是會被靜默忽略不會真正執(zhí)行。

(7)runAndReset() - 執(zhí)行并重置

boolean reset = futureTask.runAndReset();
// 用于可重復(fù)執(zhí)行的任務(wù),執(zhí)行后重置狀態(tài)

這個(gè)方法可以重復(fù)執(zhí)行,但是不能通過get得到結(jié)果。

2、

可以拋出異常。

類代碼:

import java.util.concurrent.Callable;
public class ThreadCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println("線程執(zhí)行:" + Thread.currentThread().getName());
        }
        return Thread.currentThread().getName()+"線程執(zhí)行完畢";
    }
}

主程序代碼:

 public static void main(String[] args) {
        FutureTask<String> futureTask1 = new FutureTask<>(new ThreadCallable());
        Thread thread1 = new Thread(futureTask1);
        thread1.start();
        FutureTask<String> futureTask2 = new FutureTask<>(new ThreadCallable());
        Thread thread2 = new Thread(futureTask2);
        thread2.start();
        try{
            System.out.println(futureTask1.get());
        }
        catch(Exception e){
            e.printStackTrace();
        }
        try{
            System.out.println(futureTask2.get());
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
//結(jié)果
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-1
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
線程執(zhí)行:Thread-0
Thread-0線程執(zhí)行完畢
Thread-1線程執(zhí)行完畢

4、線程池

參數(shù):

public ThreadPoolExecutor(
    int corePoolSize,              // 1. 核心線程數(shù)
    int maximumPoolSize,           // 2. 最大線程數(shù)
    long keepAliveTime,            // 3. 空閑線程存活時(shí)間
    TimeUnit unit,                 // 4. 時(shí)間單位
    BlockingQueue<Runnable> workQueue, // 5. 任務(wù)阻塞隊(duì)列
    ThreadFactory threadFactory,   // 6. 線程工廠
    RejectedExecutionHandler handler   // 7. 拒絕策略
)

corePoolSize(核心線程數(shù)):線程池中平時(shí)常駐的線程數(shù)量,即使空閑也不會被銷毀。

maximumPoolSize(最大線程數(shù)):線程池允許創(chuàng)建的最大線程數(shù)(核心線程 + 臨時(shí)線程)。

keepAliveTime(空閑存活時(shí)間):當(dāng)線程數(shù)超過核心線程數(shù)時(shí),多余的空閑線程在銷毀前等待新任務(wù)的最長時(shí)間。

unit(時(shí)間單位),為keepAliveTime的時(shí)間單位

workQueue(任務(wù)隊(duì)列):當(dāng)核心線程都在忙碌時(shí),新提交的任務(wù)會被放入這個(gè)隊(duì)列中等待。 threadFactory(線程工廠):用于創(chuàng)建新線程,通常用來給線程設(shè)置有業(yè)務(wù)意義的名稱,方便排查問題。

handler(拒絕策略):當(dāng)隊(duì)列滿了,且線程數(shù)達(dá)到了最大值時(shí),對新任務(wù)的兜底處理策略(如直接拋出異常、讓提交者自己執(zhí)行等)。

常用阻塞隊(duì)列:

ArrayBlockingQueue:

基于數(shù)組實(shí)現(xiàn)的有界阻塞隊(duì)列,初始化時(shí)必須指定容量。它采用 FIFO(先進(jìn)先出)原則,且內(nèi)部使用一把全局鎖來保證線程安全。

LinkedBlockingQueue

基于鏈表實(shí)現(xiàn)的阻塞隊(duì)列。它既可以是有界的,也可以是無界的(如果初始化時(shí)不指定容量,默認(rèn)容量為 Integer.MAX_VALUE)。它采用了讀寫分離的雙鎖機(jī)制,在高并發(fā)下吞吐量ArrayBlockingQueue 更高。注意無界時(shí)候容易棧溢出。

SynchronousQueue(零容量、手遞手)

核心特點(diǎn):一個(gè)不存儲任何元素的特殊隊(duì)列(容量為 0)。它的每次放入操作必須等待一個(gè)對應(yīng)的取出操作

生產(chǎn)建議:通常會配合較大的 maximumPoolSize,因?yàn)闆]有排隊(duì)緩沖,新任務(wù)來了必須立刻創(chuàng)建線程接手。

PriorityBlockingQueue

一個(gè)支持優(yōu)先級的無界阻塞隊(duì)列。任務(wù)不再是先進(jìn)先出,而是根據(jù)自定義的比較器或自然順序來決定執(zhí)行順序。

延遲隊(duì)列:

使用 JDK 自帶的 ScheduledThreadPoolExecutor,內(nèi)部配置了DelayedWorkQueue,這個(gè)隊(duì)列和ThreadPoolExecutor不適配。

常用拒絕策略:

AbortPolicy(默認(rèn)策略)

直接拋出一個(gè) RejectedExecutionException 運(yùn)行時(shí)異常,阻止任務(wù)提交。

CallerRunsPolicy(調(diào)用者運(yùn)行策略)

不拋出異常,也不丟棄任務(wù),而是將當(dāng)前被拒絕的任務(wù)退回到提交該任務(wù)的線程(即調(diào)用者線程)中去執(zhí)行。

適合允許延遲,任務(wù)不可丟失的的后臺任務(wù)

原理:因?yàn)檎{(diào)用者線程需要親自去執(zhí)行被拒絕的任務(wù),這會占用調(diào)用者的時(shí)間,從而自然地降低新任務(wù)提交的速度,讓系統(tǒng)在高負(fù)載下實(shí)現(xiàn)平滑降級。

DiscardPolicy(丟棄策略)

靜默地直接丟棄當(dāng)前被拒絕的任務(wù),不拋出任何異常,也不做任何通知。

DiscardOldestPolicy(丟棄最舊任務(wù)策略)

丟棄任務(wù)隊(duì)列中等待時(shí)間最長(即隊(duì)首)的那個(gè)任務(wù),然后嘗試重新提交當(dāng)前這個(gè)最新的任務(wù)。

特點(diǎn):

1、降低資源消耗,提高響應(yīng)速度(線程復(fù)用)

傳統(tǒng)方式:線程的創(chuàng)建和銷毀是非常消耗系統(tǒng)資源的操作,需要頻繁進(jìn)行系統(tǒng)調(diào)用和上下文切換。

線程池:通過預(yù)先創(chuàng)建一批線程并長期存活,任務(wù)執(zhí)行完畢后線程不會被銷毀,而是歸還到池中等待下一個(gè)任務(wù)。這種線程復(fù)用機(jī)制,極大地降低了頻繁創(chuàng)建和銷毀線程帶來的 CPU 和內(nèi)存開銷。

2、增強(qiáng)系統(tǒng)的穩(wěn)定性與可控性(避免資源耗盡)

傳統(tǒng)方式:如果無限制地手動創(chuàng)建線程,會迅速耗盡系統(tǒng)的內(nèi)存和 CPU 資源,極易導(dǎo)致系統(tǒng)卡頓甚至發(fā)生內(nèi)存溢出崩潰。

線程池:可以對線程的最大并發(fā)數(shù)進(jìn)行嚴(yán)格控制。當(dāng)任務(wù)過多時(shí),多余的任務(wù)會被放入隊(duì)列等待,或者根據(jù)預(yù)設(shè)的拒絕策略進(jìn)行處理,從而有效防止資源過載,保障系統(tǒng)的穩(wěn)定性。

3、統(tǒng)一管理與功能豐富

傳統(tǒng)方式:手動創(chuàng)建的線程分散且獨(dú)立,開發(fā)者需要自己處理線程的生命周期、同步、優(yōu)先級等,管理難度大且容易出錯(cuò)。

線程池:提供了統(tǒng)一的線程調(diào)度、生命周期管理、狀態(tài)監(jiān)控以及定時(shí)/周期性任務(wù)執(zhí)行等高級功能,大大簡化了并發(fā)編程的復(fù)雜度。

類代碼:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolUtil {
    public static ThreadPoolExecutor getThreadPoolExecutor()
    {
        return new ThreadPoolExecutor(
                5,
                10,
                60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(100),
                new ThreadPoolExecutor.DiscardOldestPolicy()
                );
    }
}

主程序代碼:

import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class main {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = ThreadPoolUtil.getThreadPoolExecutor();
        try{
            for(int i=1;i<=20;i++)
            {
                int taskId=i;
                executor.execute(()->{
                    System.out.println("任務(wù)"+taskId+"正在被"+Thread.currentThread().getName()+"執(zhí)行");
                    try{
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally{
            executor.shutdown();//不再接受新的任務(wù),線程池會等待所有任務(wù)執(zhí)行完畢,再關(guān)閉
            try {
                if(!executor.awaitTermination(60, TimeUnit.SECONDS)){//阻塞等待60秒線程池所有任務(wù)還沒有完成返回false
                    executor.shutdownNow();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        }

    }
}
//運(yùn)行結(jié)果
任務(wù)3正在被pool-1-thread-4執(zhí)行
任務(wù)4正在被pool-1-thread-5執(zhí)行
任務(wù)2正在被pool-1-thread-3執(zhí)行
任務(wù)1正在被pool-1-thread-2執(zhí)行
任務(wù)0正在被pool-1-thread-1執(zhí)行
任務(wù)5正在被pool-1-thread-4執(zhí)行
任務(wù)6正在被pool-1-thread-5執(zhí)行
任務(wù)7正在被pool-1-thread-2執(zhí)行
任務(wù)9正在被pool-1-thread-1執(zhí)行
任務(wù)8正在被pool-1-thread-3執(zhí)行
任務(wù)10正在被pool-1-thread-1執(zhí)行
任務(wù)11正在被pool-1-thread-3執(zhí)行
任務(wù)12正在被pool-1-thread-2執(zhí)行
任務(wù)13正在被pool-1-thread-5執(zhí)行
任務(wù)14正在被pool-1-thread-4執(zhí)行
任務(wù)15正在被pool-1-thread-1執(zhí)行
任務(wù)16正在被pool-1-thread-3執(zhí)行
任務(wù)17正在被pool-1-thread-4執(zhí)行
任務(wù)18正在被pool-1-thread-5執(zhí)行
任務(wù)19正在被pool-1-thread-2執(zhí)行

示例補(bǔ)充:

示例代碼中核心線程數(shù)為5個(gè),因?yàn)?0個(gè)任務(wù)并沒有超過核心線程數(shù)+隊(duì)列數(shù),所以不會啟動擴(kuò)容創(chuàng)建新線程,因?yàn)榫€程運(yùn)行中睡眠一秒,能看到輸出情況是每一秒輸出五個(gè)。

5、虛擬線程

特點(diǎn):

1、資源消耗:極致的輕量

傳統(tǒng)線程:每個(gè)線程都有一個(gè)固定的、較大的棧內(nèi)存(默認(rèn) 1MB 左右),且由操作系統(tǒng)管理。如果你嘗試創(chuàng)建幾十萬個(gè)傳統(tǒng)線程,系統(tǒng)內(nèi)存會瞬間耗盡。

虛擬線程:

它的??臻g不是連續(xù)分配的,而是按需動態(tài)伸縮的(初始只有幾 KB)。你可以輕松在一臺普通電腦上創(chuàng)建數(shù)百萬個(gè)虛擬線程,而不會導(dǎo)致內(nèi)存溢出。

2、虛擬現(xiàn)場被設(shè)置為強(qiáng)制后臺線程,哪怕繼承了主線程,JVM也不會等待。

3、應(yīng)用場景:

適合:高吞吐量的 Web 服務(wù)、微服務(wù)調(diào)用、數(shù)據(jù)庫訪問。

不適合:CPU 密集型任務(wù)(如復(fù)雜的數(shù)學(xué)計(jì)算、圖像處理)。

原因:虛擬線程的優(yōu)勢在于 I/O 阻塞時(shí)的切換。如果是純計(jì)算任務(wù),它不會阻塞,會一直占用載體線程,此時(shí)它就退化成了普通線程,且因?yàn)檎{(diào)度層多了一層,反而可能略慢。對于 CPU 密集型任務(wù),還是應(yīng)該使用傳統(tǒng)的線程池。

創(chuàng)建虛擬線程:

   Thread.Builder builder = Thread.ofVirtual().name("worker-", 0);
        for (int i = 0; i < 3; i++) {
            int taskId = i;
            builder.start(() -> {
                System.out.println("[線程3] 任務(wù) " + taskId + " 在 " + Thread.currentThread().getName() + " 中執(zhí)行");
            });
        }
        // 主線程等待1秒,讓虛擬線程有時(shí)間執(zhí)行
        Thread.sleep(1000);
//結(jié)果
[線程3] 任務(wù) 2 在 worker-2 中執(zhí)行
[線程3] 任務(wù) 0 在 worker-0 中執(zhí)行
[線程3] 任務(wù) 1 在 worker-1 中執(zhí)行
//或者更簡單的方法
//使用 Thread.startVirtualThread()
        Thread vThread1 = Thread.startVirtualThread(() -> {
            System.out.println("[線程1] 虛擬線程名稱: " + Thread.currentThread().getName());
            System.out.println("[線程1] 是否是虛擬線程: " + Thread.currentThread().isVirtual());
        });
        vThread1.join();

創(chuàng)建虛擬線程池:

  try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
            // 提交多個(gè)任務(wù)
            for (int i = 1; i <= 5; i++) {
                int taskId = i;
                executor.submit(() -> {
                    System.out.println("[線程池] 任務(wù) " + taskId + " 開始執(zhí)行 - " + Thread.currentThread().getName());
                    // 模擬 I/O 操作
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    System.out.println("[線程池] 任務(wù) " + taskId + " 完成執(zhí)行");
                    return "結(jié)果-" + taskId;
                });
            }
            // 等待所有任務(wù)完成
            executor.shutdown();
            executor.awaitTermination(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("[線程池] 所有任務(wù)已完成\n");
//結(jié)果
[線程池] 任務(wù) 3 開始執(zhí)行 - 
[線程池] 任務(wù) 2 開始執(zhí)行 - 
[線程池] 任務(wù) 5 開始執(zhí)行 - 
[線程池] 任務(wù) 1 開始執(zhí)行 - 
[線程池] 任務(wù) 4 開始執(zhí)行 - 
[線程池] 任務(wù) 1 完成執(zhí)行
[線程池] 任務(wù) 5 完成執(zhí)行
[線程池] 任務(wù) 4 完成執(zhí)行
[線程池] 任務(wù) 3 完成執(zhí)行
[線程池] 任務(wù) 2 完成執(zhí)行
[線程池] 所有任務(wù)已完成

定時(shí)任務(wù)調(diào)度線程

(1)Timer,TimerTask

原理

使用 Timer 和 TimerTask 創(chuàng)建線程,并不是一種完全獨(dú)立、全新的底層創(chuàng)建線程的方法。它本質(zhì)上是基于 Java 最基礎(chǔ)的實(shí)現(xiàn) Runnable 接口這一方式,并在此基礎(chǔ)上進(jìn)行了更高層次的封裝,專門用于實(shí)現(xiàn)定時(shí)或周期性任務(wù)。

有以下缺點(diǎn):

單線程隱患:一個(gè) Timer 只有一個(gè)工作線程。如果其中一個(gè) TimerTask 執(zhí)行時(shí)間過長,會延遲其他所有任務(wù)的執(zhí)行;更嚴(yán)重的是,如果某個(gè)任務(wù)拋出了未捕獲的異常,整個(gè) Timer 的工作線程就會直接掛掉,導(dǎo)致后續(xù)所有任務(wù)都無法再執(zhí)行。

依賴系統(tǒng)時(shí)間:Timer 是基于系統(tǒng)的絕對時(shí)間來調(diào)度的,如果操作系統(tǒng)的系統(tǒng)時(shí)間被修改,定時(shí)任務(wù)的執(zhí)行就會變得不準(zhǔn)確。

所以現(xiàn)在不常用。

(2)ScheduledThreadPoolExecutor

特點(diǎn):

1. 繼承自 ThreadPoolExecutor,這意味著它天然擁有了標(biāo)準(zhǔn)線程池的所有基礎(chǔ)能力,比如線程的復(fù)用、并發(fā)控制、線程生命周期管理等。

2、核心任務(wù)隊(duì)列:DelayedWorkQueue

底層結(jié)構(gòu):這是一個(gè)基于最小堆(Min-Heap)數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的優(yōu)先級隊(duì)列。

核心作用:它會把所有提交的任務(wù),按照“距離執(zhí)行時(shí)間”的長短進(jìn)行排序。距離下次執(zhí)行時(shí)間最近的任務(wù),永遠(yuǎn)會排在隊(duì)列的最前面(堆頂)。工作線程每次只需要盯著堆頂?shù)娜蝿?wù),如果時(shí)間沒到就繼續(xù)等待,從而實(shí)現(xiàn)了精準(zhǔn)的定時(shí)調(diào)度。

3、核心任務(wù)封裝:ScheduledFutureTask

當(dāng)你提交一個(gè)定時(shí)任務(wù)時(shí),ScheduledThreadPoolExecutor 不會直接把你的任務(wù)扔進(jìn)隊(duì)列,而是會先把它包裝成一個(gè) ScheduledFutureTask 對象

核心作用:這個(gè)包裝類里不僅包含了你的業(yè)務(wù)邏輯,還額外記錄了任務(wù)的觸發(fā)時(shí)間和周期。

周期性原理:對于周期性任務(wù),這個(gè)包裝類在執(zhí)行完一次任務(wù)后,會自動計(jì)算出下一次應(yīng)該執(zhí)行的時(shí)間,然后把自己重新塞回 DelayedWorkQueue 中排隊(duì)。這就形成了一個(gè)“執(zhí)行 -> 計(jì)算下次時(shí)間 -> 重新入隊(duì) -> 等待執(zhí)行”的完美閉環(huán)。

示例代碼:

 // 創(chuàng)建定時(shí)任務(wù)線程池
        ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(3);
        System.out.println("程序啟動時(shí)間:" + System.currentTimeMillis());
        // 1. 延遲5秒執(zhí)行一次
        scheduler.schedule(() -> {
            System.out.println("[延遲任務(wù)] 執(zhí)行時(shí)間:" + System.currentTimeMillis());
        }, 5, TimeUnit.SECONDS);
        // 2. 固定頻率執(zhí)行:初始延遲2秒,每3秒執(zhí)行一次
        scheduler.scheduleAtFixedRate(() -> {
            System.out.println("[固定頻率] 執(zhí)行時(shí)間:" + System.currentTimeMillis());
        }, 2, 3, TimeUnit.SECONDS);
        // 3. 固定延遲執(zhí)行:初始延遲1秒,每次執(zhí)行完延遲2秒
        scheduler.scheduleWithFixedDelay(() -> {
            System.out.println("[固定延遲] 執(zhí)行時(shí)間:" + System.currentTimeMillis());
            try {
                Thread.sleep(500); // 模擬任務(wù)執(zhí)行
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, 1, 2, TimeUnit.SECONDS);
        // 主線程等待15秒后關(guān)閉線程池
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        // 關(guān)閉線程池
        scheduler.shutdown();

示例補(bǔ)充:

scheduleWithFixedDelay:保證任務(wù)之間有固定的"休息時(shí)間",適合需要控制執(zhí)行頻率、避免系統(tǒng)過載的場景
scheduleAtFixedRate:保證任務(wù)按固定時(shí)間點(diǎn)執(zhí)行,適合對時(shí)間精度要求高的場景

在使用scheduleAtFixedRate的時(shí)候如果執(zhí)行時(shí)間大于設(shè)置周期,任務(wù)會一個(gè)接一個(gè)立即執(zhí)行,沒有等待時(shí)間,長時(shí)間下去會導(dǎo)致任務(wù)堆積,內(nèi)存溢出,線程饑餓等問題。

--------------------------------------------------------------------------------------------------------------------

到這里就結(jié)束嘍??????

到此這篇關(guān)于Java 線程創(chuàng)建方式全過程的文章就介紹到這了,更多相關(guān)Java 線程創(chuàng)建方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring boot將配置屬性注入到bean類中

    Spring boot將配置屬性注入到bean類中

    本篇文章主要介紹了Spring boot將配置屬性注入到bean類中,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • 解決try-catch捕獲異常信息后Spring事務(wù)失效的問題

    解決try-catch捕獲異常信息后Spring事務(wù)失效的問題

    這篇文章主要介紹了解決try-catch捕獲異常信息后Spring事務(wù)失效的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • MybatisPlus之時(shí)間處理問題

    MybatisPlus之時(shí)間處理問題

    在數(shù)據(jù)庫設(shè)計(jì)時(shí),阿里巴巴編碼規(guī)約建議使用gmt_create和gmt_modified命名時(shí)間字段,并設(shè)置為datetime類型,本文介紹了兩種自動填充時(shí)間字段的實(shí)現(xiàn)方式:SQL級別和代碼級別(使用MyBatis?Plus),SQL級別通過設(shè)置默認(rèn)值和更新值為CURRENT_TIMESTAMP
    2024-09-09
  • maven打包web項(xiàng)目時(shí)同時(shí)打包為war和jar文件的方法

    maven打包web項(xiàng)目時(shí)同時(shí)打包為war和jar文件的方法

    本篇文章主要介紹了maven打包web項(xiàng)目時(shí)同時(shí)打包為war和jar文件的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • 新手了解java 泛型基礎(chǔ)知識

    新手了解java 泛型基礎(chǔ)知識

    這篇文章主要給大家介紹了關(guān)于Java中泛型使用的簡單方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • EasyExcel與Apache POI版本沖突導(dǎo)致`NoSuchMethodError`異常的解決方法

    EasyExcel與Apache POI版本沖突導(dǎo)致`NoSuchMethodError`異常的解決方法

    本文介紹了EasyExcel與ApachePOI版本沖突導(dǎo)致`NoSuchMethodError`異常的原因,并提供了兩種解決方案:排除EasyExcel自帶的POI并手動指定統(tǒng)一版本,或者移除自己引入的POI,同時(shí),也強(qiáng)調(diào)了在使用EasyExcel時(shí)避免單獨(dú)引入POI的重要性,需要的朋友可以參考下
    2025-11-11
  • MyBatis實(shí)現(xiàn)動態(tài)SQL更新的代碼示例

    MyBatis實(shí)現(xiàn)動態(tài)SQL更新的代碼示例

    本文博小編將帶領(lǐng)大家學(xué)習(xí)如何利用 MyBatis 攔截器機(jī)制來優(yōu)雅的實(shí)現(xiàn)這個(gè)需求,文中通過代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-07-07
  • IDEA運(yùn)行java程序時(shí)總彈出提示配置Edit Configurations問題

    IDEA運(yùn)行java程序時(shí)總彈出提示配置Edit Configurations問題

    更新IDEA后,運(yùn)行Java程序時(shí)可能需要手動配置JDK版本,通過統(tǒng)一設(shè)置默認(rèn)JDK可以解決每次彈出EditConfigurations的問題,此操作可以簡化開發(fā)流程,提高效率
    2024-09-09
  • java實(shí)現(xiàn)訂餐系統(tǒng)

    java實(shí)現(xiàn)訂餐系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)訂餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • idea中配置tomcat啟動jsp項(xiàng)目過程

    idea中配置tomcat啟動jsp項(xiàng)目過程

    在IntelliJ IDEA中配置Tomcat并啟動JSP項(xiàng)目,首先需要在IDEA中安裝和配置Tomcat服務(wù)器,接著將項(xiàng)目與Tomcat關(guān)聯(lián),設(shè)置正確的部署路徑和端口號,通過這些步驟,可以實(shí)現(xiàn)JSP項(xiàng)目的本地運(yùn)行和調(diào)試,使得開發(fā)和測試工作更加高效
    2024-10-10

最新評論

台东市| 全南县| 高邮市| 华蓥市| 宾阳县| 乐业县| 云安县| 克拉玛依市| 安国市| 安徽省| 泸州市| 松阳县| 宜春市| 池州市| 武平县| 新民市| 东明县| 宣威市| 左云县| 蕉岭县| 宜兴市| 南漳县| 临清市| 余干县| 健康| 东平县| 富顺县| 红河县| 赞皇县| 西贡区| 武定县| 东海县| 台中县| 故城县| 桂林市| 五河县| 故城县| 濮阳市| 巢湖市| 蒙自县| 诸暨市|