国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【異步】Java 的 8 種異步實(shí)現(xiàn)方式

這篇具有很好參考價(jià)值的文章主要介紹了【異步】Java 的 8 種異步實(shí)現(xiàn)方式。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

異步執(zhí)行對(duì)于開發(fā)者來說并不陌生,在實(shí)際的開發(fā)過程中,很多場(chǎng)景多會(huì)使用到異步,相比同步執(zhí)行,異步可以大大縮短請(qǐng)求鏈路耗時(shí)時(shí)間,比如:發(fā)送短信、郵件。

異步的八種實(shí)現(xiàn)方式:

  1. 線程異步 Thread/Runnable
  2. Future + Callable
  3. 異步框架 CompletableFuture
  4. Spring 注解 @Async
  5. Spring ApplicationEvent 事件
  6. 第三方異步框架,比如 Hutool 的 ThreadUtil
  7. Guava 異步
  8. 消息隊(duì)列

1、線程異步

public class ThreadTest implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        new Thread(threadTest).start();
    }

}

當(dāng)然,如果每次都創(chuàng)建一個(gè) Thread 線程,頻繁的創(chuàng)建、銷毀,浪費(fèi)系統(tǒng)資源,我們可以采用線程池:【Thread】線程池的 7 種創(chuàng)建方式及自定義線程池

2、Future 異步

public class FutureTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<String> future = executor.submit(() -> {
            Thread.sleep(2000);
            return "this is future execute final result!!!";
        });
        //這里需要返回值時(shí)會(huì)阻塞主線程
        String result = future.get();
        System.out.println(result);
        executor.shutdown();
    }

}

Future的不足之處的包括以下幾點(diǎn):

  1. 無法被動(dòng)接收異步任務(wù)的計(jì)算結(jié)果:雖然我們可以主動(dòng)將異步任務(wù)提交給線程池中的線程來執(zhí)行,但是待異步任務(wù)執(zhí)行結(jié)束之后,主線程無法得到任務(wù)完成與否的通知,它需要通過get方法主動(dòng)獲取任務(wù)執(zhí)行的結(jié)果。
  2. Future件彼此孤立:有時(shí)某一個(gè)耗時(shí)很長(zhǎng)的異步任務(wù)執(zhí)行結(jié)束之后,你想利用它返回的結(jié)果再做進(jìn)一步的運(yùn)算,該運(yùn)算也會(huì)是一個(gè)異步任務(wù),兩者之間的關(guān)系需要程序開發(fā)人員手動(dòng)進(jìn)行綁定賦予,F(xiàn)uture并不能將其形成一個(gè)任務(wù)流(pipeline),每一個(gè)Future都是彼此之間都是孤立的,所以才有了后面的CompletableFuture,CompletableFuture就可以將多個(gè)Future串聯(lián)起來形成任務(wù)流。
  3. Futrue沒有很好的錯(cuò)誤處理機(jī)制:截止目前,如果某個(gè)異步任務(wù)在執(zhí)行發(fā)的過程中發(fā)生了異常,調(diào)用者無法被動(dòng)感知,必須通過捕獲get方法的異常才知曉異步任務(wù)執(zhí)行是否出現(xiàn)了錯(cuò)誤,從而在做進(jìn)一步的判斷處理

3、CompletableFuture
關(guān)于 CompletableFuture 更多詳情請(qǐng)看:【異步】Futurn、FutureTask、CompletionService、CompletableFuture

public static void thenRunAsync() throws ExecutionException, InterruptedException {
    CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread() + " cf1 do something....");
        return 1;
    });
    CompletableFuture<Void> cf2 = cf1.thenRunAsync(() -> {
        System.out.println(Thread.currentThread() + " cf2 do something...");
    });
    //等待任務(wù)1執(zhí)行完成
    System.out.println("cf1結(jié)果->" + cf1.get());
    //等待任務(wù)2執(zhí)行完成
    System.out.println("cf2結(jié)果->" + cf2.get());
}

4、Spring 注解 @Async

@Configuration
public class ThreadPoolConfig {

    @Bean("taskExecutor")
    public Executor taskExecutor() {
        //返回可用處理器的Java虛擬機(jī)的數(shù)量 12
        int i = Runtime.getRuntime().availableProcessors();
        System.out.println("系統(tǒng)最大線程數(shù)  : " + i);
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心線程池大小
        executor.setCorePoolSize(16);
        //最大線程數(shù)
        executor.setMaxPoolSize(20);
        //配置隊(duì)列容量,默認(rèn)值為Integer.MAX_VALUE
        executor.setQueueCapacity(99999);
        //活躍時(shí)間
        executor.setKeepAliveSeconds(60);
        //線程名字前綴
        executor.setThreadNamePrefix("asyncServiceExecutor -");
        //設(shè)置此執(zhí)行程序應(yīng)該在關(guān)閉時(shí)阻止的最大秒數(shù),以便在容器的其余部分繼續(xù)關(guān)閉之前等待剩余的任務(wù)完成他們的執(zhí)行
        executor.setAwaitTerminationSeconds(60);
        //等待所有的任務(wù)結(jié)束后再關(guān)閉線程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }

}
@Service
@EnableAsync
public class AsyncServiceImpl implements AsyncService {

    @Override
    @Async("taskExecutor")
    public String sendSms() {
        System.out.println(Thread.currentThread().getName());
        return null;
    }

    @Override
    @Async("taskExecutor")
    public String sendEmail() {
        System.out.println(Thread.currentThread().getName());
        return null;
    }

}

在實(shí)際項(xiàng)目中, 使用 @Async 調(diào)用線程池,推薦等方式是是使用自定義線程池的模式,不推薦直接使用 @Async 直接實(shí)現(xiàn)異步

5、Spring ApplicationEvent 事件

Spring 中使用事件只需要以下的幾個(gè)步驟:

  1. 定義事件,繼承 ApplicationEvent
  2. 定義監(jiān)聽,要么實(shí)現(xiàn) ApplicationListener 接口,要么在方法上添加 @EventListener 注解
  3. 定義發(fā)布事件接口,調(diào)用 ApplicationContext.publishEvent() 或者 ApplicationEventPublisher.publishEvent();
  4. 業(yè)務(wù)調(diào)用發(fā)布事件
@Getter
@Setter
public class BaseEvent<T> extends ApplicationEvent {

    private T data;

    public BaseEvent(Object source) {
        super(source);
    }

    public BaseEvent(Object source, T data) {
        super(source);
        this.data = data;
    }

}
@Component
public class BaseEventListener implements ApplicationListener<BaseEvent<UserVo>> {

    @Override
    @Async("taskExecutor")
    public void onApplicationEvent(BaseEvent<UserVo> baseEvent) {
        UserVo eventData = baseEvent.getData();
        // TODO 業(yè)務(wù)處理
    }

}
@Autowired
private ApplicationContext applicationContext;

@GetMapping("/pubEvent")
public void pubEvent() {
    BaseEvent<UserVo> baseEvent = new BaseEvent<>("event", new UserVo());
    applicationContext.publishEvent(baseEvent);
}

6、Hutool 的 ThreadUtil

public static void main(String[] args) {
    for (int i = 0; i < 3; i++) {
        ThreadUtil.execAsync(() -> {
            ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
            int number = threadLocalRandom.nextInt(20) + 1;
            System.out.println(number);
        });
        log.info("當(dāng)前第:" + i + "個(gè)線程");
    }

    log.info("task finish!");
}

7、 Guava 異步

public static void test() {
    ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
    final ListenableFuture<Integer> listenableFuture = executorService.submit(() -> {
        log.info("callable execute...");
        TimeUnit.SECONDS.sleep(1);
        return 1;
    });

    Futures.addCallback(listenableFuture, new FutureCallback<Integer>() {
        @Override
        public void onSuccess(@Nullable Integer integer) {
            System.out.println("Get listenable future's result with callback " + integer);
        }
        @Override
        public void onFailure(Throwable throwable) {
            throwable.printStackTrace();
        }
    }, Executors.newCachedThreadPool());
}

8、 消息隊(duì)列

常用的消息隊(duì)列:RabbitMqRocketMq文章來源地址http://www.zghlxwxcb.cn/news/detail-692576.html

到了這里,關(guān)于【異步】Java 的 8 種異步實(shí)現(xiàn)方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Java 的異步編程 (5 種異步實(shí)現(xiàn)方式詳解)

    1.創(chuàng)建一個(gè)異步線程 2.創(chuàng)建主線程,在主線程中創(chuàng)建異步線程執(zhí)行異步線程,實(shí)現(xiàn)異步編程 3.優(yōu)化:由于線程的頻繁創(chuàng)建和銷毀浪費(fèi)系統(tǒng)資源,我們可以使用線程池進(jìn)行優(yōu)化 線程池的使用:創(chuàng)建一個(gè)類,將線程池設(shè)置為全局變量 執(zhí)行線程時(shí)只需要?jiǎng)?chuàng)建執(zhí)行對(duì)象調(diào)用執(zhí)行方法就

    2024年02月14日
    瀏覽(57)
  • Java實(shí)現(xiàn)異步的8種方式

    Java實(shí)現(xiàn)異步的8種方式

    一、前言 ????????異步執(zhí)行對(duì)于開發(fā)者來說并不陌生,在實(shí)際的開發(fā)過程中,很多場(chǎng)景多會(huì)使用到異步,相比同步執(zhí)行,異步可以大大縮短請(qǐng)求鏈路耗時(shí)時(shí)間,比如:「發(fā)送短信、郵件、異步更新等」,這些都是典型的可以通過異步實(shí)現(xiàn)的場(chǎng)景。???? 二、異步的八種實(shí)

    2024年02月09日
    瀏覽(19)
  • Java實(shí)現(xiàn)異步的幾種方式

    Java實(shí)現(xiàn)異步的幾種方式

    普通線程實(shí)現(xiàn)異步,但頻繁創(chuàng)建、銷毀線程比較耗資源,所以一般交給線程池執(zhí)行 結(jié)果: Future異步 和普通線程實(shí)現(xiàn)異步區(qū)別不大,只是使用Future是要獲取執(zhí)行后的返回值 結(jié)果: Spring的@Async異步 使用@Async注解實(shí)現(xiàn)異步的前提是需要在啟動(dòng)類上標(biāo)注@EnableAsync來開啟異步配置

    2024年02月04日
    瀏覽(39)
  • Java實(shí)現(xiàn)Kafka消費(fèi)者及消息異步回調(diào)方式

    Kafka 在創(chuàng)建消費(fèi)者進(jìn)行消費(fèi)數(shù)據(jù)時(shí),由于可以理解成為是一個(gè)kafka 的單獨(dú)線程,所以在Kafka消費(fèi)數(shù)據(jù)時(shí)想要在外部對(duì)消費(fèi)到的數(shù)據(jù)進(jìn)行業(yè)務(wù)處理時(shí)是獲取不到的,所以就需要實(shí)現(xiàn)一個(gè)消息回調(diào)的接口來進(jìn)行數(shù)據(jù)的保存及使用。 消息回調(diào)接口實(shí)現(xiàn)代碼如下 Kafka消費(fèi)者代碼實(shí)現(xiàn)如

    2024年02月06日
    瀏覽(34)
  • 面試題2023:Java線程的實(shí)現(xiàn)方式

    這是一道頻率出現(xiàn)比較高的面試題,像阿里、騰訊、京東的Java初中級(jí)工程師面試題都出現(xiàn)過、面試過了薪水也能拿個(gè)10K~20K,所以掌握這些基礎(chǔ)的知識(shí)還是有必要的。 啟動(dòng)線程使用的是start方法,這樣會(huì)啟動(dòng)一個(gè)新的線程,并執(zhí)行線程的任務(wù)。如果直接調(diào)用run方法,則可以執(zhí)

    2023年04月27日
    瀏覽(12)
  • Java 實(shí)現(xiàn)多線程的三種方式

    1、三種方法的介紹和比較 1、1三種方式得介紹 1、繼承Thread類 2、實(shí)現(xiàn)Runnable接口 3、實(shí)現(xiàn)Callable接口 1、2三種方法的介紹和比較 1、2、1、實(shí)現(xiàn)Runnable接口相比繼承Thread類有如下優(yōu)勢(shì) 1、增強(qiáng)程序的健壯性,將業(yè)務(wù)邏輯與線程調(diào)度分離 2、線程池只能放入實(shí)現(xiàn)Runable或Callable類線程

    2024年02月02日
    瀏覽(22)
  • Java 多線程實(shí)現(xiàn)的三種方式

    Java 多線程實(shí)現(xiàn)方式主要有三種:繼承 Thread 類、實(shí)現(xiàn) Runnable 接口、使用 ExecutorService、Callable、Future 實(shí)現(xiàn)有返回結(jié)果的多線程。其中前兩種方式線程執(zhí)行完后都沒有返回值,只有最后一種是帶返回值的。 1、繼承 Thread 類實(shí)現(xiàn)多線程 繼承 Thread 類的方法盡管被我列為一種多線程

    2023年04月27日
    瀏覽(23)
  • 線程方法接收參數(shù)示例,Java的兩種線程實(shí)現(xiàn)方式區(qū)別

    總所周知,Java實(shí)現(xiàn)多線程有兩種方式,分別是繼承Thread類和實(shí)現(xiàn)Runable接口,那么它們的區(qū)別是什么? 繼承 Thread 類: 通過繼承 Thread 類,你可以創(chuàng)建一個(gè)直接表示線程的類。你可以覆蓋 Thread 類中的 run 方法來定義線程的邏輯。當(dāng)調(diào)用 start 方法啟動(dòng)線程時(shí),會(huì)執(zhí)行該類中的

    2024年02月11日
    瀏覽(54)
  • 線程方法接收參數(shù)和返回參數(shù),Java的兩種線程實(shí)現(xiàn)方式對(duì)比

    總所周知,Java實(shí)現(xiàn)多線程有兩種方式,分別是繼承Thread類和實(shí)現(xiàn)Runable接口,那么它們的區(qū)別是什么? 繼承 Thread 類: 通過繼承 Thread 類,你可以創(chuàng)建一個(gè)直接表示線程的類。你可以覆蓋 Thread 類中的 run 方法來定義線程的邏輯。當(dāng)調(diào)用 start 方法啟動(dòng)線程時(shí),會(huì)執(zhí)行該類中的

    2024年02月11日
    瀏覽(29)
  • 如何在Java實(shí)現(xiàn)TCP方式發(fā)送和接收Socket消息(多線程模式)

    如何在Java實(shí)現(xiàn)TCP方式發(fā)送和接收Socket消息(多線程模式)

    在Java編程中,使用TCP協(xié)議進(jìn)行Socket通信是非常常見的場(chǎng)景。本文將詳細(xì)介紹如何在Java中實(shí)現(xiàn)TCP方式發(fā)送和接收Socket消息,并且利用多線程模式來提高通信效率。 首先,我們需要?jiǎng)?chuàng)建一個(gè)Server端來處理接收到的Socket連接請(qǐng)求。以下是實(shí)現(xiàn)的步驟: 創(chuàng)建一個(gè)ServerSocket對(duì)象,并指

    2024年02月12日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包