Tag Archives: solution

Asynchronous processing of HTTP request by Java_ Method 2: through deferredresult

1.DeferredResult

Spring supports HTTP asynchronous return

2. Asynchronous processing

Start a new thread, process the data and return the value.

3. Code examples

1)controller

package com.liuxd.controller;

import com.liuxd.entity.Responses;
import com.liuxd.service.TaskService2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

@Slf4j
@RestController
public class AsyncCtr2 {

    @Autowired
    private TaskService2 taskService2;

    @GetMapping(value = "/getResult")
    public DeferredResult<Responses<String>> getResult() {
        log.info("HTTP request received...");
        long startTime = System.currentTimeMillis();

        DeferredResult<Responses<String>> deferredResult = new DeferredResult<Responses<String>>();

        new Thread(new Runnable() {
            @Override
            public void run() {
                taskService2.getData(deferredResult);
            }
        }).start();

        log.info("The task of the receiving HTTP request thread has been completed, exit!");
        long endTime = System.currentTimeMillis();
        log.info("http Total request time. " + (endTime - startTime) + "ms");

        return deferredResult;

    }
}

2)service

package com.liuxd.service;

import com.liuxd.entity.Responses;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;

@Slf4j
@Service
public class TaskService2 {

    public void getData(DeferredResult<Responses<String>> deferredResult) {

        log.info("Call service asynchronous with return method, start execution...");
        long startTime = System.currentTimeMillis();

        try {
            Thread.sleep(2500L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        log.info("Call service asynchronous has return method, the end of execution!!!") ;

        long endTime = System.currentTimeMillis();
        log.info("Total time taken to call service asynchronous return method. " + (endTime - startTime) + "ms");

        deferredResult.setResult(new Responses<>(0, "Done", "SUCCESS"));

    }


}

3)Responses

package com.liuxd.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Responses<T> {

    private Integer code;

    private String msg;

    private T data;

}

4) Print results

5) Result analysis

1) The HTTP main thread accepts the request and ends after processing the request

2) After the asynchronous thread ends, returns the

Three ways of thread sequence alternate execution in Java lock free programming

1. Principle analysis

Atomicinteger is thread safe, and autoincrement is thread safe.

2. Code examples

package com.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class TasksTest extends Thread {
    private static AtomicInteger atomic = new AtomicInteger(1);
    private int id;

    public TasksTest(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        while (atomic.get() <= 12) {
            while (atomic.get() % 3 == id) {
                System.out.println("thread_" + id + " output:" + atomic.get());
                atomic.incrementAndGet();
            }
        }
    }

    public static void main(String[] args) {
        Thread thread0 = new TasksTest(0);
        Thread thread1 = new TasksTest(1);
        Thread thread2 = new TasksTest(2);

        ExecutorService exec = Executors.newFixedThreadPool(3);

        exec.submit(thread0);
        exec.submit(thread1);
        exec.submit(thread2);

        exec.shutdown();

    }
}

Implementation of retrial mechanism in Java

Keywords: thread, thread pool, queue, task scheduling

1. Retrying tool class

package com.iretry;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Retry Tools Class
 */
@Slf4j
public class RetryUtils {

    private final static int DEFAULT_RETRY_TIMES = 6;
    private final static int[] DEFAULT_DELAY_SECONDS = {3, 30, 180, 600, 1800, 3600};

    private static Queue<RetryRunnable> TASK_QUEUE = new ConcurrentLinkedQueue<>();

    public static ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    public static ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();

    static {
        //Configure the number of core threads
        executor.setCorePoolSize(10);
        // Configure the maximum number of threads
        executor.setMaxPoolSize(20);
        //configure queue size
        executor.setQueueCapacity(1000);
        //configure the name prefix of the threads in the thread pool
        executor.setThreadNamePrefix("async_");
        // rejection-policy: how to handle new tasks when the pool has reached max size
        // CALLER_RUNS: instead of executing the task in a new thread, the caller's thread will execute it
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //Perform initialization
        executor.initialize();

        scheduler.setThreadNamePrefix("scheduler_");
        scheduler.setPoolSize(5);
        scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        scheduler.initialize();
    }

    public RetryUtils() {
        //Check every second: iterate through the task queue, if needed, the thread pool schedules execution
        scheduler.scheduleAtFixedRate(() -> {
            for (RetryRunnable task : TASK_QUEUE) {
                long nextRetryMillis = task.nextRetryMillis;
                if (nextRetryMillis != -1 && nextRetryMillis <= System.currentTimeMillis()) {
                    task.nextRetryMillis = -1;
                    executor.execute(task);
                }
            }
        }, 1000);
    }

    public void doRetry(Task task) {
        doRetry(DEFAULT_RETRY_TIMES, DEFAULT_DELAY_SECONDS, task);
    }

    public void doRetry(int maxRetryTime, Task task) {
        doRetry(maxRetryTime, DEFAULT_DELAY_SECONDS, task);
    }

    public void doRetry(int[] retryDelaySeconds, Task task) {
        doRetry(retryDelaySeconds.length, retryDelaySeconds, task);
    }

    /**
     * @param maxRetryTime      Maximum number of retries
     * @param retryDelaySeconds array of retry interval times
     * @param task task
     */
    public void doRetry(final int maxRetryTime, final int[] retryDelaySeconds, final Task task) {
        Runnable runnable = new RetryRunnable(maxRetryTime, retryDelaySeconds, task);
        executor.execute(runnable);
    }

    /**
     * Custom Threads Class
     */
    private static class RetryRunnable implements Runnable {

        private final Task task;
        private final int maxRetryTimes;
        private final int[] retryDelaySeconds;

        private int retryTimes;
        private volatile long nextRetryMillis;

        //Constructors
        public RetryRunnable(final int maxRetryTimes, final int[] retryDelaySeconds, final Task task) {
            this.task = task;
            if (maxRetryTimes <= 0) {
                this.maxRetryTimes = DEFAULT_RETRY_TIMES;
            } else {
                this.maxRetryTimes = maxRetryTimes;
            }
            if (retryDelaySeconds == null || retryDelaySeconds.length == 0) {
                this.retryDelaySeconds = DEFAULT_DELAY_SECONDS;
            } else {
                this.retryDelaySeconds = retryDelaySeconds;
            }
        }

        //Implementation of business methods
        @Override
        public void run() {
            try {

                task.run();

            } catch (Throwable e) {
                int sleepSeconds = retryTimes < retryDelaySeconds.length ?retryDelaySeconds[retryTimes] : retryDelaySeconds[retryDelaySeconds.length - 1];

                if (retryTimes < maxRetryTimes) {
                    if (retryTimes == 0) {
                        TASK_QUEUE.add(this);
                        log.error("task executed error, " + sleepSeconds + " seconds do next... ", e);
                    } else {
                        log.error("retry " + retryTimes + " times error, " + sleepSeconds + " seconds do next... ", e);
                    }
                    nextRetryMillis = System.currentTimeMillis() + sleepSeconds * 1000;

                } else {
                    log.error("retry " + retryTimes + " times error", e);
                    log.error("retry snapshot: {}", JSON.toJSONStringWithDateFormat(task.snapshot(), "yyyy-MM-dd HH:mm:ss"));

                    TASK_QUEUE.remove(this);
                    task.retryFailed(e);

                }

                retryTimes++;

            }
        }
    }

}

2. Business class interface

package com.iretry;

public interface Task {

    void run() throws Exception;

    default void retryFailed(Throwable e) {
    }

    default Object snapshot() {
        return null;
    }
}

3. Test class

package com.iretry;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
public class IRetryTest {

    public static void main(String[] args) {
        RetryUtils retryUtils = new RetryUtils();

        IRetryTest iRetryTest = new IRetryTest();
        iRetryTest.executeBusiness(retryUtils, new IRetryTest().new UserInfo("Jack"));

    }

    //Business methods that require retries
    private void executeBusiness(RetryUtils retryUtils, UserInfo user) {

        retryUtils.doRetry(new int[]{6, 12}, new Task() {
            @Override
            public void run() throws Exception {
                user.setName("Henry");
                log.info("Execute the operation, change the name of the employee to: " + user.getName());
                Integer a = 1/0;

            }

            // Support rollback operations after final failure
            @Override
            public void retryFailed(Throwable e) {
                user.setName("Jack");
                log.info("Retry failed, business data rolled back...") ;
                log.info("Username is called." + user.getName());
            }

            @Override
            public Object snapshot() {
                return user;
            }
        });
    }


    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private class UserInfo {
        private String name;
    }


}

4. Implementation results

Split log by date in log4j2 of spring boot

1、application.yml

logging:
  config: classpath:log4j2.xml

2、log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
    <Properties>
        <!--System variable ${sys:logPath:-/var/logs} Retrieve the value of the system variable logPath, or set the default value if it is empty./var/logs-->
       <Property name="LOG_HOME">${sys:catalina.home:-.}/logs</Property>
        <Property name="LOG_BACK_HOME">${sys:catalina.home:-.}/logs/backup</Property>
        <Property name="LOG_PATTERN_LAYOUT">%date %highlight{[%-5.5level]}{STYLE=Logback} [%-10.10thread] [%X{employeeCode}] [%X{X-B3-TraceId}/%X{X-B3-SpanId}] %cyan{[%-50.50class:%-4.4line]} - %msg%xEx%n </Property>
        <Property name="DEFAULT_CHARSET">UTF-8</Property>
        <Property name="ERROR_FILE_NAME">error</Property>
        <Property name="INFO_FILE_NAME">info</Property>
    </Properties>

    <Appenders>
        <!-- Configure daily logs -->
        <RollingFile name="${INFO_FILE_NAME}" fileName="${LOG_HOME}/${INFO_FILE_NAME}.log" filePattern="${LOG_BACK_HOME}/$${date:yyyy-MM}/${INFO_FILE_NAME}-%d{yyyy-MM-dd}.log.gz" append="true">
            <PatternLayout charset="${DEFAULT_CHARSET}" pattern="${LOG_PATTERN_LAYOUT}"/>
            <!-- Setting Policy -->
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
            <DefaultRolloverStrategy >
                <!--Delete log from 30 days ago-->
                <Delete basePath="${LOG_BACK_HOME}" maxDepth="2">
                    <IfFileName glob="*/*.log.gz" />
                    <IfLastModified age="30d" />
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
        <!-- Configuration error log -->
        <RollingFile name="${ERROR_FILE_NAME}" fileName="${LOG_HOME}/${ERROR_FILE_NAME}.log" filePattern="${LOG_BACK_HOME}/$${date:yyyy-MM}/${ERROR_FILE_NAME}-%d{yyyy-MM-dd}.log.gz" append="true">
            <PatternLayout charset="${DEFAULT_CHARSET}" pattern="${LOG_PATTERN_LAYOUT}"/>
            <!-- Setting Policy -->
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
            <Filters>
                <!--Logs with levels greater than or equal to WARN can be written-->
                <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
        </RollingFile>
    </Appenders>

    <Loggers>
        <Logger name="org.springframework" level="INFO" additivity = "false">
            <AppenderRef ref="${INFO_FILE_NAME}"/>
            <AppenderRef ref="${ERROR_FILE_NAME}"/>
        </Logger>
        <Logger name="com.picc" level="DEBUG" additivity = "false">
            <AppenderRef ref="${INFO_FILE_NAME}"/>
            <AppenderRef ref="${ERROR_FILE_NAME}"/>
        </Logger>
        <Root level="INFO">
            <AppenderRef ref="${INFO_FILE_NAME}"/>
            <AppenderRef ref="${ERROR_FILE_NAME}"/>
        </Root>
    </Loggers>
</Configuration>

3. Use result display

cd backup/

You’ll find monthly backups

 cd 2020-06/

Log is compressed, self decompression view

Code case of XXL job executor

1. POM is introduced. Note: the version number should be consistent with XXL job admin.

       <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-job-core</artifactId>
            <version>1.9.2-SNAPSHOT</version>
        </dependency>

2、application.yml

xxl:
  job:
    admin:
      addresses: http://47.102.168.36:9500
    executor:
      log-path: ${catalina.home:/usr}/logs/job
      log-retention-days: 30
      ip: 127.0.0.1
      port: 10001

3. Configure executor bean

import com.xxl.job.core.executor.XxlJobExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * xxl-job config
 */
@Configuration
public class XxlJobConfig {
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);

    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;

    @Value("${spring.application.name}")
    private String appName;

    @Value("${xxl.job.executor.ip}")
    private String ip;

    @Value("${xxl.job.executor.port}")
    private Integer port;

    @Value("${xxl.job.executor.log-path}")
    private String logPath;

    @Value("${xxl.job.executor.log-retention-days}")
    private int logRetentionDays;


    @Bean(initMethod = "start", destroyMethod = "destroy")
    public XxlJobExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobExecutor xxlJobExecutor = new XxlJobExecutor();
        xxlJobExecutor.setAdminAddresses(adminAddresses);
        xxlJobExecutor.setAppName(appName);
        xxlJobExecutor.setIp(ip);
        xxlJobExecutor.setPort(port);
        xxlJobExecutor.setPort(-1);
        xxlJobExecutor.setAccessToken(null);
        xxlJobExecutor.setLogPath(logPath);
        xxlJobExecutor.setLogRetentionDays(logRetentionDays);
        return xxlJobExecutor;
    }
}

4. Task code

import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * JOB
 */
@JobHandler(value = "iFlyTenantJob")
@Component
public class IFlyTenantJob extends IJobHandler {

    private static final Logger log = LoggerFactory.getLogger(IFlyTenantJob.class);

    @Override
    public ReturnT<String> execute(String s) {
        XxlJobLogger.log("The mission begins...") ;
        log.info("Task started...");

        iFlyAiService.queryTenants();
        try {
            Thread.sleep(6000);
            //int a = 1/0;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        XxlJobLogger.log("End of mission...");
        log.info("End of mission...");
        return ReturnT.SUCCESS;

    }


}

Spring boot uses thread pool to realize asynchronous processing without return and asynchronous processing with return

1. Scene

HTTP requests are processed asynchronously;

1) No need to return, such as sending SMS, push messages, e-mail and other ancillary services, asynchronous processing, reduce the total time consumption of HTTP requests, improve customer experience.

2) If you need to return, the front-end will wait for the business processing result data, and the asynchronous processing will return to the main thread of HTTP request, and return to the front-end; if it is a single business that can be optimized here, please check the previous and next articles in this blog; if it is multiple business processing, you can use multiple asynchronous processing with return, and the total weight will summarize the result and return.

2. Knowledge points

1) Thread pool threadpooltaskexecutor

2) Note: @ enableasync, @ async (“asyncserviceexecutor”)

3) Return value encapsulates future & lt; T & gt;, new asyncresult & lt; & gt; (T)

3. Code examples

1)controller

package com.liuxd.controller;

import com.liuxd.entity.Responses;
import com.liuxd.service.TaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.Future;

@Slf4j
@RestController
public class AsyncCtr {

    @Autowired
    private TaskService taskService;

    @RequestMapping(value = "/get", method = RequestMethod.GET)
    public Responses<String> getResult() throws Exception {

        log.info("HTTP request received...") ;
        long startTime = System.currentTimeMillis();

        //1. Asynchronous execution_processing_data_without_waiting
        taskService.handleData();

        //2. Asynchronous execution_processing_data_waiting_for_processing_results
        Future<String> future = taskService.getData();
        String result = future.get();

        log.info("Receiving HTTP request thread task completed, exit!") ;
        long endTime = System.currentTimeMillis();
        log.info("Total time spent on http request. " + (endTime - startTime) + "ms");

        return new Responses<>(0, result, "SUCCESS");

    }

}

2)service

package com.liuxd.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;

@Slf4j
@Service
public class TaskService {

    @Async("asyncServiceExecutor")
    public void handleData() {

        log.info("Call service no return asynchronous method, start execution...");
        long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(2500L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        log.info("Call service no return asynchronous method, the end of execution!!!") ;
        long endTime = System.currentTimeMillis();
        log.info("Total time taken to call service without return asynchronous method. " + (endTime - startTime) + "ms");

    }

    @Async("asyncServiceExecutor")
    public Future<String> getData(){

        log.info("Call service has return asynchronous method, start execution...");
        long startTime = System.currentTimeMillis();

        try {
            Thread.sleep(2500L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        log.info("Call service has returned asynchronous methods, the end of execution!!!") ;

        long endTime = System.currentTimeMillis();
        log.info("Total time to call service with return asynchronous method: " + (endTime - startTime) + "ms");

        return new AsyncResult<>("Asynchronous processing completed!");

    }


}

3) Thread pool

package com.liuxd.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @program: unif-insure-service
 * @description: Thread Pool
 **/
@Configuration
@EnableAsync
public class ExecutorConfig {
    @Bean
    public Executor asyncServiceExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //Configure the number of core threads
        executor.setCorePoolSize(5);
        // Configure the maximum number of threads
        executor.setMaxPoolSize(5);
        //configure queue size
        executor.setQueueCapacity(1000);
        //configure the name prefix of the threads in the thread pool
        executor.setThreadNamePrefix("async-system-");

        // rejection-policy: How to handle new tasks when the pool has reached its max size
        // CALLER_RUNS: instead of executing the task in the new thread, the caller's thread will execute it
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //Execution initialization
        executor.initialize();
        return executor;
    }
}

4)Responses

package com.liuxd.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Responses<T> {

    private Integer code;

    private String msg;

    private T data;

}

5) Print results

6) Result analysis

1) There are three threads, HTTP request main thread, asynchronous no return thread, asynchronous return thread

2) The main thread does not need to wait for no return thread, it will wait for the result of return thread, and finally return

Asynchronous processing of HTTP request by Java_ Method 1: through callable

1.Callable

1) Runnable, which performs an independent task but does not return a value. If you want a return value after the task is completed, you can use the callable interface;

2) Callable is a paradigm with type parameters. Its type parameter method is expressed as the value returned by the method call () instead of run (), and it must be used ExecutorService.submint () method.

difference:

1. Callable, which accepts a generic type and returns a value of this type in the call() method; however, runnable’s run() method has no return value;
2. Callable, whose call() method can throw an exception, while runnable’s run() method does not.

2. Business scenario:

In HTTP requests, the business processing process takes a long time, such as large queries, remote calls and other scenarios. The main thread that receives HTTP requests will be occupied all the time, and the number of threads in Tomcat thread pool is limited. Therefore, the number of HTTP requests accepted per unit time will decrease.

3. Code examples

1)controller

package com.liuxd.controller;

import com.liuxd.entity.Responses;
import com.liuxd.service.BusinessService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.Callable;

@Slf4j
@RestController
public class AsyncCallableController {

    @Autowired
    private BusinessService businessService;

    @GetMapping(value = "/getData")
    public Callable<Responses<String>> getData() {

        log.info("HTTP request received...");

        Callable<Responses<String>> data = (() -> {
            return businessService.getData();
        });

        log.info("The task of the receiving HTTP request thread has been completed, exit!");

        return data;
    }

}

2) service

package com.liuxd.service;

import com.liuxd.entity.Responses;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class BusinessService {

    public Responses<String> getData(){

        log.info("Call the service method and start the execution...");

        try {
            Thread.sleep(2500L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        log.info("Call service method, end of execution!");

        return new Responses<>(0,"Done","SUCCESS");

    }

}

3) Print results

Asynchronous callback case of Java callback function

1. Callback function classification

Callback function distinction: synchronous callback and asynchronous callback

Synchronous callback: the meaning is only to complete the method call;

Asynchronous call: concurrency can be realized, and the main business thread can be released in time; asynchronous thread completes the work, executes callback function, and completes the aftermath work; the execution efficiency is improved.

2. Code examples

1. Note testing

package com.callback2;

public class AsyncCallBack {

    public static void main(String[] args) {
        System.out.println("Start of the main business thread ID:" + Thread.currentThread().getId());
        System.out.println("------------------");

        Son son = new Son();
        Mother mother = new Mother(son);

        mother.notice();
        son.writeHomeWork();

        System.out.println("End of the main business thread ID:" + Thread.currentThread().getId()+"\n");

    }

}

2. Mother

package com.callback2;

public class Mother {
    private Son son;
    public Mother(Son son) {
        this.son = son;
    }

    public void notice() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Notify the mother of the thread ID." + Thread.currentThread().getId());
                cookFood("Bread");
            }
        }).start();
    }

    public void cookFood(String bread) {
        System.out.println("Current cooking thread ID." + Thread.currentThread().getId());
        try {
            System.out.println("Mother Baking" + bread + "...");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Mother has baked the bread");
        String message = "Ming, come and eat!";

        son.callback(message);

    }

}

3. My son Xiao Ming

package com.callback2;

public class Son {
    private String status = "";

    public void writeHomeWork() {
        System.out.println("Xiaoming writing homework thread ID: " + Thread.currentThread().getId());
        System.err.println("Ming is writing his homework...") ;
        setStatus("Writing homework");
    }


    public void callback(String message) {
        System.out.println("Callback Xiaoming meal thread ID: " + Thread.currentThread().getId());
        System.err.println(message);
        System.err.println("Okay, coming right up!") ;
        System.out.println("Ming started eating!") ;
        setStatus("Eating in progress");
        System.out.println("Xiaoming executing meal thread ID." + Thread.currentThread().getId());
    }

    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
}

4. Implementation results

Business Main Thread Start ID: 1
------------------
Xiaoming writing homework thread ID: 1
Xiaoming writing homework in progress...
Business main thread end ID:1

Notify mother thread ID:12
Currently cooking thread ID:12
Mother baking bread...
Mother baked the bread
Callback to Xiaoming to eat Thread ID: 12
Ming, come and eat!
Okay, coming right up!
Ming starts eating!
Xiaoming executes meal thread ID: 12

5. Result analysis

1) Xiao Ming uses the main thread to do his homework (if he can’t finish it, he doesn’t need to care);

2) Mother uses the new thread to cook [concurrent], mother finishes the meal, executes the callback function, and notifies Xiao Ming to eat;

3) Xiao Ming uses a new thread and starts to eat.

Java callback function implementation case

1. What is a callback function

Callback function is a function called by function pointer. If you pass a function pointer (address) as a parameter to another function, when the pointer is used to call the function it points to, we say it is a callback function. In Java, pointers are called references. </ u> the callback function is not called directly by the implementer of the function, but by another party when a specific event or condition occurs, which is used to respond to the event or condition.

A callback method is any method that is called by another method with the callback method as its first parameter. Many times, a callback is a method that is called when something happens.

2. Application scenarios

Event driven mechanism

For example: Party A hires Party B to repair the car; then Party A goes to do other things; Party B notifies Party A that the car has been repaired, please come and get it. There is no need for Party A to wait for Party B to finish repairing the car.

3. Code examples

1. Test class

package com.callBack;
public class CallBckTest {

    public static void main(String[] args) {
        MainBusiness mainBusiness = new MainBusiness();

        System.out.println("*********The specific implementation class implements the callback method *********");
        mainBusiness.execute(new CallbackServiceImpl());

        System.out.println("********* anonymous internal class implements the callback method ********* flexible *********");
        mainBusiness.execute(new CallbackService() {
            public void callBackFunc() {
                System.out.println("The anonymous internal class callback function started executing...") ;
                System.out.println("Anonymous internal class callback function ends execution...\n");
            }
        });
    }
}

2. Business class and method

package com.callBack;
public class MainBusiness {

    private CallbackService callback;

    public void execute(CallbackService callback) {
        this.callback = callback;
        callBack();
    }

    public void callBack() {
        callback.callBackFunc();
    }
}

3. Callback function interface

package com.callBack;
//Callback functions of the interface and methods
public interface CallbackService {
    void callBackFunc();
}

4. Callback function implementation class

package com.callBack;
public class CallbackServiceImpl implements CallbackService {
    @Override
    public void callBackFunc() {
        System.out.println("The concrete implementation class callback function starts execution...") ;
        System.out.println("Concrete implementation class callback function ends execution...\n");
    }
}

5. Print results

*********Concrete implementation class implements the callback method *********
Concrete implementation class callback function starts execution...
Concrete implementation class callback function ends execution...

********* callback methods implemented by anonymous internal classes *********
Anonymous internal class callback function start execution...
Anonymous internal class callback function ends execution...

Solution: configuration of multiple front ends separated from front end and back end of nginx

1. Business scenarios

According to the business requirements, the front-end code needs to distinguish between the main business code and the sub business code.

2. Solutions

Routing is based on the root of the relative path.

3. Configuration file

  server {
        listen       9207;
        server_name  192.168.30.158;
        root /home/qdfinance/apps/pages/insure_wx/;

        #Front-end dependent business code pages are routed with relative paths to root/h5
        location /h5/ {
          root    /home/qdfinance/apps/pages/insure_wx_h5/;
          add_header Cache-Control "no-cache, no-store";
          rewrite ^/h5/(.*)$ /index.html  break;
        }
		#Reverse proxy tomcat service
        location/{
           proxy_set_header Host $host:$server_port;
           proxy_pass   http://192.168.80.192:8098/;
           root /home/qdfinance/apps/pages/insure_wx/;
           error_page 404 /index.html;
        }
		#Front-end main business code page
        location   =/{
          root /home/qdfinance/apps/pages/insure_wx/;
          add_header Cache-Control "no-cache, no-store";
        }
        location /index.html {
          root  /home/qdfinance/apps/pages/insure_wx/;
          add_header Cache-Control "no-cache, no-store";
        }
        location /statich5/ {
           root /home/qdfinance/apps/pages/insure_wx_h5/; 
        } 
  
        location /static/ {
          root  /home/qdfinance/apps/pages/insure_wx/;
        }
        location /detail/ {
          rewrite ^/(.*)$ /index.html last;
        }
		location /me {
          rewrite ^/(.*)$ /index.html last;
        }
        location /login/ {
          rewrite ^/(.*)$ /index.html last;
        }
        location /customer {
          rewrite ^/(.*)$ /index.html last;
        }
        location /customer-add {
          rewrite ^/(.*)$ /index.html last;
        }
        location /subscribe {
          rewrite ^/(.*)$ /index.html last;
        }
        location /order {
          rewrite ^/(.*)$ /index.html last;
        }
        location /order-detail {
          rewrite ^/(.*)$ /index.html last;
        }
        location /main {
          rewrite ^/(.*)$ /index.html last;
        }
        location /auth {
          rewrite ^/(.*)$ /index.html last;
        }
        location /policy {
          rewrite ^/(.*)$ /index.html last;
        }
        location /intellect {
          rewrite ^/(.*)$ /index.html last;
        }
		location /intellectanswerlist {
          rewrite ^/(.*)$ /index.html last;
        }
		location /immed {
          rewrite ^/(.*)$ /index.html last;
        }
        location /docking {
          rewrite ^/(.*)$ /index.html last;
        }
		location /success {

          rewrite ^/(.*)$ /index.html last;
        }
		location /error {
          rewrite ^/(.*)$ /index.html last;
        }
    }

[How to Solve] Java nested object @validated is not valid

1. Controller layer

@ApiOperation(value = "port")
    @PostMapping("/ygbx/regular")
    public Long regular(@Validated @RequestBody OrderCheckRegularVO vo) {
        return orderCheckService.saveRegular(vo);
    }

2. Main Vo

Solution: add @valid to the VO declaration inside the main vo

@Data
@ApiModel(description = "VO")
public class OrderCheckRegularVO extends OrderCheckBaseVO {

    @NotNull
    @Valid
    private ProductYgbxRegularVO price;

    @NotNull
    @Valid
    private OrderCheckRegularPolicyInfoVO policyInfo;

    @NotNull
    @Valid
    private OrderCheckChargeInfoVO chargeInfo;

    @NotNull
    @Valid
    private OrderCheckBenefitTotalVO benefitInfo;

    @NotEmpty
    @Valid
    private List<OrderCheckKindVO> kindList;


}