>  기사  >  Java  >  Java에서 @Async에 의해 비동기적으로 호출되는 메서드

Java에서 @Async에 의해 비동기적으로 호출되는 메서드

PHPz
PHPz앞으로
2023-05-05 19:10:041714검색

    서문

    비동기 호출과 동기 호출

    • 동기 호출: 순차적으로 실행하고, 호출로 결과를 반환하고, 다음 호출을 다시 실행

    • 비동기 호출: 기다리지 않고 다음 호출을 실행합니다. 반환될 결과

    1. @Async 설명

    @Async의 주석 코드는 다음과 같습니다.

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

    Annotation은 유형 및 메소드에서 사용할 수 있습니다.
    값은 값으로 정의되며 기본값은 비어 있습니다

    일반적으로 이 주석은 @EnableAsync 와 일치해야 하며 원본 코드는 다음과 같습니다

    @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;
    }

    구성 시작을 위해 이 주석을 통해 주로 시작 클래스에 배치됩니다.

    시작 클래스에 다음을 추가합니다.

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

    2.

    2.1 동기 호출

    함수 결과는 호출부터 반환까지만 실행할 수 있습니다. 동기 호출이라고 하는 한 단계

    서비스 레이어 코드:

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

    제어 레이어 코드 모듈:

    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();
            }
        }
        
    }

    시작 클래스를 통해 시작한 후 springboot

    출력은 다음과 같습니다.

    Start

    // 5초 동안 기다리는 것입니다. 터미널이 표시되거나 닫히지도 않습니다.

    End

    2.2 비동기 호출

    비동기 호출, 실행 함수는 반환 결과를 기다리지 않고 다음 단계를 실행하세요

    서비스 레이어 코드:
    이 메소드를 식별하기 위해 주로 @Async 주석을 추가합니다

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

    제어 레이어 코드 모듈:

    서비스 레이어 함수를 호출하여 @EnableAsync를 시작

    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();
            }
        }
        
    }

    그리고 시작 클래스에 주석 추가

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

    3. 스레드 풀 사용자 정의

    스레드 풀에 대한 기본 지식은 이전 기사를 참조하세요.

    Java에서 스레드 및 스레드 풀을 올바르게 닫는 방법(코드 연습에는 소스 코드가 포함됨) 분석)
    Java 스레드 풀 생성 방법 상세 분석(전체)

    스레드 풀을 지정하지 않으면 기본으로 사용되는 스레드 풀은 SimpleAsyncTaskExecutor입니다(작업이 오면 그냥 스레드를 생성하면 됩니다. 계속해서 스레드를 생성하면 CPU가 너무 높아서 OOM이 발생함). 내장 스레드 풀에는 일반적으로 단점이 있습니다. 일반적으로 ThreadPoolExecutor를 사용하는 것이 좋습니다(스레드 풀의 리소스를 지우고 위험을 피하세요)

    자세한 내용은 다음과 같습니다.

      newFixedThreadPool: 스레드 수가 고정되어 있어도 작업 대기열은 여전히 ​​무제한이므로(최대 스레드 수는 대기열이 가득 찼을 때만 생성됩니다) OOM
    • newCachedThreadPool: 없습니다. 최대 스레드 수에 대한 상한 및 많은 수의 스레드가 생성됩니다. 쉽게 동결하거나 직접 OOM
    • 스레드 풀 구성은 더 나은 리소스 활용을 위해 사용자 정의 스레드 풀을 통해 조정할 수 있습니다

    @Async 이 주석은 다음을 찾습니다. AsyncConfigurer 인터페이스(구현 클래스는 AsyncConfigurerSupport, 기본 구성 및 메서드는 비어 있음), 스레드 풀을 지정하기 위해 인터페이스를 재정의할 수 있습니다.

      AsyncConfigurer 인터페이스 구현
    • AsyncConfigurerSupport 상속
    • Custom TaskExecutor(내장 작업 실행기 대체)
    • 세 번째 방법:

    애플리케이션에서 일부 스레드 풀 정의 .xml 변수

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

    커스텀 스레드 풀은 다음과 같습니다

    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;
        }
    }

    위 내용은 Java에서 @Async에 의해 비동기적으로 호출되는 메서드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제