国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

實(shí)現(xiàn)異步的九種方式,你知道幾個(gè)?

開發(fā) 前端
我們?nèi)粘i_發(fā)的時(shí)候,經(jīng)常說到異步編程。比如說,在注冊(cè)接口,我們?cè)谟脩糇?cè)成功時(shí),用異步發(fā)送郵件通知用戶。那么,小伙伴們,你知道實(shí)現(xiàn)異步編程,一共有多少種方式嗎?我給大家梳理了9種!

前言

大家好,我是田螺。

我們?nèi)粘i_發(fā)的時(shí)候,經(jīng)常說到異步編程。比如說,在注冊(cè)接口,我們?cè)谟脩糇?cè)成功時(shí),用異步發(fā)送郵件通知用戶。

那么,小伙伴們,你知道實(shí)現(xiàn)異步編程,一共有多少種方式嗎?我給大家梳理了9種~~

  • 使用Thread和Runnable
  • 使用Executors提供線程池
  • 使用自定義線程池
  • 使用Future和Callable
  • 使用CompletableFuture
  • 使用ForkJoinPool
  • Spring的@Async異步
  • MQ實(shí)現(xiàn)異步
  • 使用Hutool工具庫的ThreadUtil

1. 使用Thread和Runnable

Thread和Runnable是最基本的異步編程方式,直接使用Thread和Runnable來創(chuàng)建和管理線程。

public class Test {
    public static void main(String[] args) {
        System.out.println("田螺主線程:" + Thread.currentThread().getName());
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("田螺異步線程測試:"+Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.start();
    }
}

但是呢,日常工作中,不推薦直接使用Thread和Runnable,因?yàn)樗羞@些缺點(diǎn):

  • 資源消耗大:每次創(chuàng)建新線程會(huì)消耗系統(tǒng)資源,頻繁創(chuàng)建和銷毀線程會(huì)導(dǎo)致性能下降。
  • 難以管理:手動(dòng)管理線程的生命周期、異常處理、任務(wù)調(diào)度等非常復(fù)雜。
  • 缺乏擴(kuò)展性:無法輕松控制并發(fā)線程的數(shù)量,容易導(dǎo)致系統(tǒng)資源耗盡。
  • 線程復(fù)用問題:每次任務(wù)都創(chuàng)建新線程,無法復(fù)用已有的線程,效率低下。

2.使用Executors提供線程池

針對(duì)Thread和Runnable的缺點(diǎn),我們可以使用線程池呀,線程池主要有這些優(yōu)點(diǎn):

  • 它幫我們管理線程,避免增加創(chuàng)建線程和銷毀線程的資源損耗。因?yàn)榫€程其實(shí)也是一個(gè)對(duì)象,創(chuàng)建一個(gè)對(duì)象,需要經(jīng)過類加載過程,銷毀一個(gè)對(duì)象,需要走GC垃圾回收流程,都是需要資源開銷的。
  • 提高響應(yīng)速度。如果任務(wù)到達(dá)了,相對(duì)于從線程池拿線程,重新去創(chuàng)建一條線程執(zhí)行,速度肯定慢很多。
  • 重復(fù)利用。線程用完,再放回池子,可以達(dá)到重復(fù)利用的效果,節(jié)省資源。

有些小伙伴說,我們可以直接使用Executors提供的線程池呀,非常快捷方便,比如:

- Executors.newFixedThreadPool
- Executors.newCachedThreadPool

簡單demo代碼如下:

public class Test {
    public static void main(String[] args) {
        System.out.println("田螺主線程:" + Thread.currentThread().getName());
        ExecutorService executor = Executors.newFixedThreadPool(3);
        
        executor.execute(()->{
            System.out.println("田螺線程池方式,異步線程:" + Thread.currentThread().getName());
        });
    }
}
//  運(yùn)行結(jié)果:
田螺主線程:main
田螺線程池方式,異步線程:pool-1-thread-1

3. 使用自定義線程池

使用使用Executors提供線程池,如newFixedThreadPool,雖然簡單快捷,但是呢,它的阻塞隊(duì)列十無界的!

newFixedThreadPool默認(rèn)使用LinkedBlockingQueue作為任務(wù)隊(duì)列,而LinkedBlockingQueue是一個(gè)無界隊(duì)列(默認(rèn)容量為Integer.MAX_VALUE)。如果任務(wù)提交速度遠(yuǎn)大于線程池處理速度,隊(duì)列會(huì)不斷堆積任務(wù),最終可能導(dǎo)致內(nèi)存耗盡.

因此,我們一般推薦使用自定義線程池,來開啟異步。

public class Test {
    public static void main(String[] args) {
        // 自定義線程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, // 核心線程數(shù)
                4, // 最大線程數(shù)
                60, // 空閑線程存活時(shí)間
                TimeUnit.SECONDS, // 時(shí)間單位
                new ArrayBlockingQueue<>(8), // 任務(wù)隊(duì)列
                Executors.defaultThreadFactory(), // 線程工廠
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略
        );

        System.out.println("田螺主線程:" + Thread.currentThread().getName());
        executor.execute(() -> {
            try {
                Thread.sleep(500); // 模擬耗時(shí)操作
                System.out.println("田螺自定義線程池開啟異步:" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }
}
//輸出
田螺主線程:main
田螺自定義線程池開啟異步:pool-1-thread-1

4. 使用Future和Callable

有些小伙伴說,如果我們期望異步編程可以返回結(jié)果呢?

那我們可以使用Future和Callable。Future和Callable是Java 5引入的,用于處理異步任務(wù)。Callable類似于Runnable,但它可以返回一個(gè)結(jié)果,并且可以拋出異常。Future表示異步計(jì)算的結(jié)果。

簡單使用demo:

public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException  {
        // 自定義線程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, // 核心線程數(shù)
                4, // 最大線程數(shù)
                60, // 空閑線程存活時(shí)間
                TimeUnit.SECONDS, // 時(shí)間單位
                new ArrayBlockingQueue<>(8), // 任務(wù)隊(duì)列
                Executors.defaultThreadFactory(), // 線程工廠
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略
        );

        System.out.println("田螺主線程:" + Thread.currentThread().getName());

        Callable<String> task = () -> {
            Thread.sleep(1000); // 模擬耗時(shí)操作
            System.out.println("田螺自定義線程池開啟異步:" + Thread.currentThread().getName());
            return "Hello, 公眾號(hào):撿田螺的小男孩!";
        };

        Future<String> future = executor.submit(task);

        String result = future.get(); // 阻塞直到任務(wù)完成
        System.out.println("異步結(jié)果:"+result);
    }
}

運(yùn)行結(jié)果:
田螺主線程:main
田螺自定義線程池開啟異步:pool-1-thread-1
異步結(jié)果:Hello, 公眾號(hào):撿田螺的小男孩!

5. 使用CompletableFuture

CompletableFuture是Java 8引入的,提供了更強(qiáng)大的異步編程能力,支持鏈?zhǔn)秸{(diào)用、異常處理、組合多個(gè)異步任務(wù)等。

簡單使用demo:

public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException  {
        // 自定義線程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, // 核心線程數(shù)
                4, // 最大線程數(shù)
                60, // 空閑線程存活時(shí)間
                TimeUnit.SECONDS, // 時(shí)間單位
                new ArrayBlockingQueue<>(8), // 任務(wù)隊(duì)列
                Executors.defaultThreadFactory(), // 線程工廠
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略
        );

        System.out.println("田螺主線程:" + Thread.currentThread().getName());

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000); // 模擬耗時(shí)操作
                System.out.println("田螺CompletableFuture開啟異步:" + Thread.currentThread().getName());
                return "Hello, 公眾號(hào):撿田螺的小男孩!";
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello, 公眾號(hào):撿田螺的小男孩!";
        },executor);

        future.thenAccept(result -> System.out.println("異步結(jié)果:" + result));
        future.join();
    }
}

6. 使用ForkJoinPool

有些時(shí)候,我們希望開啟異步,將一個(gè)大任務(wù)拆分成多個(gè)小任務(wù)(Fork),然后將這些小任務(wù)的結(jié)果合并(Join)。這時(shí)候,我們就可以使用ForkJoinPool啦~。

ForkJoinPool 是 Java 7 引入的一個(gè)線程池實(shí)現(xiàn),專門用于處理分治任務(wù)。

  • 它的特點(diǎn)就是任務(wù)拆分(Fork)和結(jié)果合并(Join),以及工作竊取(Work-Stealing)。
  • ForkJoinPool 特別適合處理遞歸任務(wù)或可以分解的并行任務(wù)。

簡單使用demo:

public class Test {
    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool(); // 創(chuàng)建 ForkJoinPool
        int result = pool.invoke(new SumTask(1, 100)); // 提交任務(wù)并獲取結(jié)果
        System.out.println("1 到 100 的和為: " + result);
    }

    static class SumTask extends RecursiveTask<Integer> {
        private final int start;
        private final int end;

        SumTask(int start, int end) {
            this.start = start;
            this.end = end;
        }

        @Override
        protected Integer compute() {
            if (end - start <= 10) { // 直接計(jì)算小任務(wù)
                int sum = 0;
                for (int i = start; i <= end; i++) sum += i;
                return sum;
            } else { // 拆分任務(wù)
                int mid = (start + end) / 2;
                SumTask left = new SumTask(start, mid);
                SumTask right = new SumTask(mid + 1, end);
                left.fork(); // 異步執(zhí)行左任務(wù)
                return right.compute() + left.join(); // 等待左任務(wù)完成并合并結(jié)果
            }
        }
    }

}

7. Spring的@Async異步

Spring 提供了 @Async 注解來實(shí)現(xiàn)異步方法調(diào)用,非常方便。使用 @Async 可以讓方法在單獨(dú)的線程中執(zhí)行,而不會(huì)阻塞主線程。

Spring @Async 的使用步驟其實(shí)很簡單:

  • 啟用異步支持:在 Spring Boot項(xiàng)目中,需要在配置類或主應(yīng)用類上添加 @EnableAsync 注解。
  • 標(biāo)記異步方法:在需要異步執(zhí)行的方法上添加 @Async 注解。
  • 配置線程池:默認(rèn)情況下,Spring 使用一個(gè)簡單的線程池。如果需要自定義線程池,可以通過配置實(shí)現(xiàn)。

啟用異步支持:

@SpringBootApplication
@EnableAsync // 啟用異步支持
public class AsyncDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(AsyncDemoApplication.class, args);
    }
}

異步服務(wù)類

@Service
public class TianLuoAsyncService {

    @Async // 標(biāo)記為異步方法
    public void asyncTianLuoTask() {
        try {
            Thread.sleep(2000); // 模擬耗時(shí)操作
            System.out.println("異步任務(wù)完成,線程: " + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

默認(rèn)情況下,Spring 使用一個(gè)簡單的線程池(SimpleAsyncTaskExecutor),每次調(diào)用都會(huì)創(chuàng)建一個(gè)新線程。因此,在使用Spring的@Async進(jìn)行異步時(shí),推薦使用自定義線程池。

如下:

@Configuration
public class AsyncConfig {

    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10); // 核心線程數(shù)
        executor.setMaxPoolSize(20);  // 最大線程數(shù)
        executor.setQueueCapacity(50); // 隊(duì)列容量
        executor.setThreadNamePrefix("AsyncThread-"); // 線程名前綴
        executor.initialize();
        return executor;
    }
}

然后,在 @Async 注解中指定線程池的名稱:

@Async("taskExecutor") // 指定使用自定義的線程池
public void asyncTianLuoTask() {
    // 方法邏輯
}

8. MQ實(shí)現(xiàn)異步

我們?cè)谔岬組Q的時(shí)候,經(jīng)常提到,它有異步處理、解耦、流量削鋒。是的,MQ經(jīng)常用來實(shí)現(xiàn)異步編程。

簡要代碼如下:先保存用戶信息,然后發(fā)送注冊(cè)成功的MQ消息

// 用戶注冊(cè)方法
  public void registerUser(String username, String email, String phoneNumber) {
      // 保存用戶信息(簡化版)
      userService.add(buildUser(username,email,phoneNumber))
      // 發(fā)送消息
      String registrationMessage = "User " + username + " has registered successfully.";
      // 發(fā)送消息到隊(duì)列
      rabbitTemplate.convertAndSend("registrationQueue", registrationMessage);
  }

消費(fèi)者從隊(duì)列中讀取消息并發(fā)送短信或郵件:

@Service
public class NotificationService {

    // 監(jiān)聽消息隊(duì)列中的消息并發(fā)送短信/郵件
    @RabbitListener(queues = "registrationQueue")
    public void handleRegistrationNotification(String message) {
        // 這里可以進(jìn)行短信或郵件的發(fā)送操作
        System.out.println("Sending registration notification: " + message);

        // 假設(shè)這里是發(fā)送短信的操作
        sendSms(message);

        // 也可以做其他通知(比如發(fā)郵件等)
        sendEmail(message);
    }
  }

9.使用Hutool工具庫的ThreadUtil

可以使用的是類似 Hutool 工具庫中的 ThreadUtil,它提供了豐富的線程池管理和異步任務(wù)調(diào)度功能。

先引入依賴:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.11</version> <!-- 請(qǐng)使用最新版本 -->
</dependency>

最簡單的,可以直接使用ThreadUtil.execute執(zhí)行異步任務(wù)

public class Test {
    public static void main(String[] args) {
        System.out.println("田螺主線程");
        ThreadUtil.execAsync(
                () -> {
                    System.out.println("田螺異步測試:" + Thread.currentThread().getName());
                }
        );
    }
}
//輸出
田螺主線程
田螺異步測試:pool-1-thread-1

責(zé)任編輯:武曉燕 來源: 撿田螺的小男孩
相關(guān)推薦

2018-04-03 15:38:07

Java單例模式模式設(shè)計(jì)

2021-05-07 16:19:36

異步編程Java線程

2025-01-21 10:04:40

Java并發(fā)阻塞隊(duì)列

2019-08-21 08:44:52

RPC框架Java

2021-08-05 07:28:25

Java實(shí)現(xiàn)方式

2021-03-04 15:48:05

微服務(wù)語言開源

2022-07-01 08:00:44

異步編程FutureTask

2024-06-19 19:17:04

2024-08-26 12:18:07

Python代碼存根

2023-10-30 11:53:37

繼承JS父類

2025-03-25 10:49:13

2013-10-14 14:55:44

編程開發(fā)工具

2024-03-01 13:48:00

Git配置系統(tǒng)

2023-05-17 12:33:11

AI人工智能

2025-06-12 03:55:00

項(xiàng)目處理異常代碼

2021-11-04 11:54:30

Linux內(nèi)存系統(tǒng)

2022-07-05 08:05:00

策略模式接口實(shí)現(xiàn)類

2016-12-19 14:35:10

機(jī)器人工作

2024-04-24 11:24:43

C#數(shù)據(jù)去重

2024-11-12 14:56:07

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

制服丝袜影音| 日本道免费精品一区二区三区| 亚洲成av人影院在线观看| 一级黄色香蕉视频| 一区二区三区日韩| 日韩电影在线观看完整版| 亚洲男帅同性gay1069| 天堂av在线网站| 国产麻豆成人传媒免费观看| 欧美主播福利视频| 日本www在线观看| 成人免费看的视频| 韩国成人av| 91在线一区| 精品视频久久久| 男人av在线| 亚洲一区二区三区视频在线| 欧美区高清在线| 九九在线高清精品视频| 亚洲精品视频在线播放| 日本黄网站色大片免费观看| 成人在线tv视频| 亚洲国产成人精品电影| 欧美 国产 小说 另类| 韩国v欧美v日本v亚洲v| 好男人社区在线视频| 国产一区二区三区观看| 欧美成人免费在线观看| 亚洲熟妇无码一区二区三区| 成人污污视频| 26uuu精品一区二区| 亚洲欧美精品一区二区| 国产一区二区中文字幕免费看| 国产一二区视频| 成人影院av| 欧美精品第1页| 亚洲精品中字| 日本福利视频| 国内综合精品午夜久久资源| 在线观看91视频| 韩国v欧美v日本v亚洲| 国产成人手机视频| 手机在线观看av| 国产嫩草影院久久久久| 国产成人免费av电影| 国产真实乱子伦| 91九色精品国产一区二区| 黑人巨大精品欧美一区二区一视频| 久久久噜噜噜久久久| 国产传媒视频在线观看| 久久伊人中文字幕| 成年人免费视频观看| 传媒视频在线| 久久午夜激情| 日日摸日日碰夜夜爽无码| 亚洲一二三区不卡| 不卡一二三区| 狠狠色狠狠色综合人人| 99久久精品免费| h片在线免费| 91日本在线视频| 亚洲乱码精品一二三四区日韩在线| 在线免费观看黄| 欧美一级高清免费| 欧美国产日韩在线观看| 123成人网| 欧美视频在线第一页| 日韩视频免费观看高清完整版 | 欧美一区二区三区视频| 91麻豆精品| 国产区一区二区| 国产精品视频第一区| 美洲精品一卡2卡三卡4卡四卡| 欧美乱妇40p| 老司机精品福利视频| 色噜噜一区二区| 99久久99精品久久久久久| 天天综合网天天做天天受| 91捆绑美女网站| 黄色免费看片| 国产日韩欧美精品| 欧美日韩日日摸| 在线看女人毛片| 欧美日韩中文字幕一区| 四虎免费av| 91丨国产丨九色丨pron| 伊大人久久香线焦宗合一75大| 国产一级网站视频在线| 欧美日韩成人综合天天影院| 99精品国产99久久久久久福利| 日韩动漫在线观看| 亚洲国产国产亚洲一二三| 亚洲第一级黄色片| 精品国产精品久久一区免费式| 日韩av播放器| 成人黄色网免费| 黑人精品xxx一区一二区| 成人情趣视频网站| 97人人在线| 日本10禁啪啪无遮挡免费一区二区 | 正在播放亚洲| 亚洲国产精品嫩草影院久久| 日韩黄色一级片| 日韩三区免费| www.99av| 92福利视频午夜1000合集在线观看| 精品久久久久久久久中文字幕 | 一本一道久久a久久精品综合蜜臀| 欧美美女啪啪| 在线观看黄网| 日韩国产精品一区二区三区| 中文字幕精品一区二区精品| 国产精品欧美极品| 国产精品成久久久久| 毛片在线看片| 欧美成人高潮一二区在线看| 538国产精品一区二区免费视频| 亚洲福利一二三区| 9色精品在线| 色综合久久久| 人人在线97| 免费看国产精品一二区视频| 综合欧美国产视频二区| 亚洲精选免费视频| 久热re这里精品视频在线6| 大型av综合网站| 亚洲丝袜一区| 中文字幕国内自拍| 国产精品日韩一区二区| 国产亚洲欧洲黄色| 欧美日韩精品欧美日韩精品| 国产精品日韩久久久| а√最新版地址在线天堂| 九九精品在线观看| 韩国av一区二区三区| 亚洲一区二区三区成人| 日韩一区二区三区免费观看| 日韩高清不卡一区二区| 成人无遮挡免费网站视频在线观看| 久久亚洲中文字幕无码| 成人av片网址| 久久人人爽人人爽人人片av高请| 日韩欧美精品网址| 国产日韩精品一区| 国产伦理精品不卡| 六月天综合网| 亚洲精品123区| 久久99蜜桃| 女人av一区| 青草综合视频| 91xxx在线观看| 蜜桃日韩视频| 亚洲色图15p| 国产成人综合自拍| 黑人精品一区| 日韩中文字幕亚洲精品欧美| 337p亚洲精品色噜噜| 亚洲成av人片一区二区梦乃| 亚洲男人都懂的| 成人a区在线观看| 成熟亚洲日本毛茸茸凸凹| 丝袜脚交一区二区| 麻豆视频观看网址久久| 久久久久国产精品| 91精品在线观看国产| 国产精品www994| 亚洲欧美综合| 久久婷婷一区| 国产精品一级片在线观看| 日本少妇一区二区| 国产精品自拍网站| 国产高清久久久| 国产.精品.日韩.另类.中文.在线.播放| 麻豆精品在线播放| 99国产精品久久久久久久久久 | 国产精品国产三级国产aⅴ无密码| 久久精品在这里| 午夜精品久久久久久久| 在线观看日韩av先锋影音电影院| 欧美日韩一区小说| 日韩中文有码在线视频| 国产精品美女www爽爽爽视频| 日韩国产精品一区二区| 超碰在线97免费| 国产高清在线看| 韩国美女久久| 五月激激激综合网色播| 日日摸夜夜添夜夜添国产精品| 国产亚洲欧美在线| 欧美日韩中文字幕日韩欧美| 亚洲大胆人体av| 成人福利在线观看| 自慰无码一区二区三区| h视频在线播放| 精品一区91| 免费成人性网站| 色伊人久久综合中文字幕| 欧美夫妻性生活xx| 男人j进女人j| 国产乱视频在线观看|