Rumah  >  Artikel  >  Java  >  Kaedah dipanggil asynchronously oleh @Async dalam java

Kaedah dipanggil asynchronously oleh @Async dalam java

PHPz
PHPzke hadapan
2023-05-05 19:10:041766semak imbas

    Prekata

    Panggilan tak segerak dan panggilan segerak

    • Panggilan segerak: pelaksanaan berurutan, kembalikan hasilnya dengan panggilan Laksanakan panggilan seterusnya

    • Panggilan tak segerak: Dengan membuat panggilan, tidak perlu menunggu hasil pemulangan, laksanakan panggilan seterusnya

    1. Penjelasan @Async

    Kod anotasi @Async adalah seperti berikut:

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Async {
        String value() default "";
    }

    Anotasi boleh digunakan dalam jenis dan kaedah
    Tentukan nilainya melalui nilai, lalainya kosong

    Secara amnya, anotasi ini perlu dipadankan @EnableAsync, kod asal adalah seperti berikut

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import({AsyncConfigurationSelector.class})
    public @interface EnableAsync {
        Class<? extends Annotation> annotation() default Annotation.class;
    
        boolean proxyTargetClass() default false;
    
        AdviceMode mode() default AdviceMode.PROXY;
    
        int order() default Integer.MAX_VALUE;
    }

    Terutamanya letakkan anotasi ini dalam kelas permulaan untuk permulaan konfigurasi

    Tambah yang berikut dalam kelas permulaan:

    @SpringbootApplication
    @EnableAsync
    public class Application{
        public static void main(String[] args){
            SrpingApplication.run(Application.class, args);
        }
    }

    2. Penggunaan

    2.1 Panggilan segerak

    Langkah seterusnya hanya boleh dilaksanakan daripada panggilan ke hasil fungsi yang dikembalikan, yang dipanggil segerak panggil

    Kod lapisan perkhidmatan:

    public class Service{
        public void test01() throws InterruptedException{
            Thread.sleep(5000);
            System.out.println("保存日志");
        }
    }

    Modul kod lapisan kawalan:

    public class Controler{
        @Autowired
        private Service service;
    
        @GetMapping("/test")
        public String getTest(){
            try{
                System.out.println("开始");
                service.test01();
                System.out.println("结束");            
            }catch(InterruptedException e){
                e.prinStackTrace();
            }
        }
        
    }

    Selepas bermula melalui kelas permulaan springboot

    Keluaran adalah seperti berikut:

    Mula

    // Ini untuk menunggu selama 5 saat, terminal tidak Paparan tidak ditutup

    Tamat

    2.2 Panggilan tak segerak

    Panggilan tak segerak, fungsi pelaksana boleh melaksanakan langkah seterusnya tanpa menunggu hasil pemulangan

    kod Lapisan perkhidmatan:
    Terutamanya menambah anotasi @Async untuk mengenal pasti kaedah ini

    public class Service{
        @Async
        public void test01() throws InterruptedException{
            Thread.sleep(500);
            System.out.println("保存日志");
        }
    }

    Modul kod lapisan kawalan:

    Dengan memanggil fungsi lapisan perkhidmatan

    public class Controler{
        @Autowired
        private Service service;
    
        @GetMapping("/test")
        public String getTest(){
            try{
                System.out.println("开始");
                service.test01();
                System.out.println("结束");            
            }catch(InterruptedException e){
                e.prinStackTrace();
            }
        }
        
    }

    dan dalam kelas permulaan Tambah anotasi untuk memulakan @EnableAsync

    @SpringbootApplication
    @EnableAsync
    public class Application{
        public static void main(String[] args){
            SrpingApplication.run(Application.class, args);
        }
    }

    3. Kumpulan benang tersuai

    Untuk pengetahuan asas tentang kumpulan benang, sila lihat artikel saya sebelum ini:

    Cara menutup benang dalam Java Dan kumpulan benang dengan betul (amalan kod termasuk analisis kod sumber)
    Analisis terperinci tentang cara membuat kumpulan benang java (penuh)

    Jika anda tidak menentukan kumpulan benang, kumpulan benang lalai yang digunakan ialah SimpleAsyncTaskExecutor (buat satu apabila tugas datang) Benang, penciptaan benang yang berterusan kepada CPU dan OOM yang berlebihan). Kumpulan benang terbina dalam secara amnya mempunyai kelemahan Umumnya disyorkan untuk menggunakan ThreadPoolExecutor (kosongkan sumber kumpulan benang untuk mengelakkan risiko)

    Butirannya adalah seperti berikut:

    • newFixedThreadPool: Bilangan utas ditetapkan, tetapi baris gilir tugasan masih tidak terhad (bilangan maksimum utas hanya akan dibuat apabila baris gilir penuh), jadi ia akan menyebabkan OOM

    • newCachedThreadPool: Tiada had atas untuk bilangan maksimum utas adalah terdedah kepada ketinggalan atau mengarahkan OOM

    Anda. boleh melaraskan konfigurasi kumpulan benang melalui kumpulan benang tersuai, yang lebih baik Penggunaan sumber

    Anotasi @Async mencari antara muka AsyncConfigurer (kelas pelaksanaan ialah AsyncConfigurerSupport, konfigurasi lalai dan kaedah kosong), jadi antara muka boleh ditulis semula untuk menentukan kumpulan benang.

    • Mewarisi AsyncConfigurerSupport

    • dengan melaksanakan antara muka AsyncConfigurer

    • Peranti)

    Kaedah ketiga:

    Tentukan beberapa pembolehubah kumpulan benang dalam aplikasi.xml

    thread.core.size=16
    thread.max.size=16
    thread.queue.size=30
    
    thread.prefix=xx-

    Sesuaikan kumpulan benang seperti berikut

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    import java.util.concurrent.ThreadPoolExecutor;
    
    @Configuration
    public class ThreadPoolConfig {
        // 线程名称前缀
        @Value("${thread.prefix}")
        private String threadPrefix;
        
        // 核心线程数
        @Value("${thread.core.size}")
        private int coreSize;
    
        // 最大线程数
        @Value("${thread.max.size}")
        private int maxSize;
        
        // 队列长度
        @Value("${thread.queue.size}")
        private int queueSize;
        
        // 通过bean注解注入
        @Bean("xx")
        public ThreadPoolTaskExecutor taskExecutor() {
            ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
            //设置线程池参数信息
            taskExecutor.setCorePoolSize(coreSize);
            taskExecutor.setMaxPoolSize(maxSize);
            taskExecutor.setQueueCapacity(queueSize);
            taskExecutor.setThreadNamePrefix(threadPrefix);
            taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
            taskExecutor.setAwaitTerminationSeconds(30);
            
            //修改拒绝策略为使用当前线程执行
            taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            
            //初始化线程池
            taskExecutor.initialize();
            return taskExecutor;
        }
    }

    Atas ialah kandungan terperinci Kaedah dipanggil asynchronously oleh @Async dalam java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam