Multithreading combat

I. Introduction

In the program, the code is executed sequentially, but the way this order execution efficiency is very low in some cases, it took dinner here as example, the New Year to eat a lot of good, for example, you have two home wok, a pressure cooker (with time but is only one), you eat pork stew, then fry ten dishes, only one person doing mom, mom first bowl of soup, fried first and then a dish, so order execution down. But the family was waiting ah, too slow is not it? At this time if the mother of the three pot at the same time with them, we can fry two dishes and a pork stew. This is equivalent to the inside of the pot thread pool, is the mother of cpu (core ah). This time the mother's life have learned to play with the two cooking pots, a pot with a bowl of soup, each pot is at the same time, but each pot dish cooked but not necessarily together, while her mother came through the method of tasting determine whether the food has been cooked, and this is the thread returns the result.

Second, the environment and ideas

spring boot项目
任务通过设置任务key来区别不同的任务,如果任务执行成功,则返回该任务key,否则返回error,代表任务失败,同时附带失败原因码和说明。

Third, actual

1, the thread pool configuration class ThreadPoolConfig

package com.zlc.multithreading.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 11:49
 **/
@Configuration
public class ThreadPoolConfig {

    /**
     * 核心线程池的大小是:75
     * 线程池的最大数量:125
     * 空闲线程的存活时间:180000毫秒
     * 空闲线程的存活时间的单位:ms
     * 工作队列:基于链表结构的阻塞队列
     * 饱和策略:没有声明默认采用CallerRunsPolicy (由调用线程处理该任务)
     */
    @Bean
    public ExecutorService getThreadPool(){
        return new ThreadPoolExecutor(75,
                125,
                180000,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingDeque<>(450),
                new ThreadPoolExecutor.CallerRunsPolicy());
    }
}

2, a package task returns the object TaskResponseModel

package com.zlc.multithreading.model;

import lombok.Data;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 11:44
 **/
@Data
public class TaskResponseModel {
    
    private String key;
    
    private Integer resultCode;
    
    private String resultMessage;
    
}

3, task request parameter object RequestObjectModel

package com.zlc.multithreading.model;

import lombok.Data;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 10:44
 **/
@Data
public class RequestObjectModel {
    
    private String key;
    
    private Object params;
    
    private Object request;
    
}

4, multi-threaded task TaskExecutor

package com.zlc.multithreading.task;

import com.zlc.multithreading.constance.TaskConstance;
import com.zlc.multithreading.model.TaskResponseModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 11:47
 **/
@Component
public class TaskExecutor {
    
    private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class);

    /**
     * 线程池
     */
    private final ExecutorService executorService;

    public TaskExecutor(ExecutorService executorService) {
        this.executorService = executorService;
    }

    /**
     * 执行任务,任务列表需要从外边构造好,然后传进来
     **/
    public List<TaskResponseModel> execute(List<Callable<TaskResponseModel>> commands) {
        //创建异步执行对象
        CompletionService<TaskResponseModel> completionService = new ExecutorCompletionService<>(executorService);
        for (Callable<TaskResponseModel> command : commands) {
            completionService.submit(command);
        }

        //响应参数
        int taskCount = commands.size();
        List<TaskResponseModel> params = new ArrayList<>(taskCount);
        try {
            for (int i = 0; i < taskCount; i++) {
                Future future = completionService.take();
                params.add((TaskResponseModel) future.get());
            }
        } catch (InterruptedException | ExecutionException e) {
            TaskResponseModel taskResponseModel = new TaskResponseModel();
            taskResponseModel.setKey(TaskConstance.TASK_ERROR);
            params.add(taskResponseModel);
            logger.error(e.getMessage());
        }
        return params;
    }
}

5, create 5 test business service, different sleep time for each business to represent different business processing time
1) TestServiceOne

package com.zlc.multithreading.service;

import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 14:30
 **/
public interface TestServiceOne {
   TaskResponseModel testOne(String key, RequestObjectModel requestObjectModel); 
}

package com.zlc.multithreading.service;

import com.zlc.multithreading.constance.TaskConstance;
import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;
import org.springframework.stereotype.Service;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 14:41
 **/
@Service
public class TestServiceOneImpl implements TestServiceOne{
    
    @Override
    public TaskResponseModel testOne(String key, RequestObjectModel requestObjectModel) {
        TaskResponseModel taskResponseModel = new TaskResponseModel();
        // 测试一的处理流程
        long startTime = System.currentTimeMillis();
        try {
            // 让这个任务休眠100毫秒
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
            // 根据具体业务校验或者是处理或者该任务抛出异常的话,返回的key为error
            taskResponseModel.setKey(TaskConstance.TASK_ERROR);
            // 可以将resultCode和resultMessage统一定义一下
            // 比如说将测试一的返回码设置为1开头
            // 测试一任务异常  设置为子code为10000,对应的message为  任务一系统异常
            // 将 没通过某种规则  设置为子code为 11000, 对应的message为 没通过任务一校验规则
            // 以此类推
            taskResponseModel.setResultCode(TaskConstance.TASK_ONE_EXPECTION_CODE);
            taskResponseModel.setResultMessage("测试一任务异常啦,异常信息为:" + e.getMessage());
        }
        long endTime = System.currentTimeMillis();
        // 如果没有异常和出发不通过规则,则返回你想返回的数据,demo以返回处理时间为例
        taskResponseModel.setKey(TaskConstance.TASK_ONE_KEY);
        taskResponseModel.setResultCode(TaskConstance.TASK_SUCCESS_CODE);
        taskResponseModel.setResultMessage("测试一任务处理时间为:" + (endTime-startTime) + "毫秒");
        return taskResponseModel;
    }
}

2) TestServiceTwo

package com.zlc.multithreading.service;

import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 14:31
 **/
public interface TestServiceTwo {
    
    TaskResponseModel testTwo(String key, RequestObjectModel requestObjectModel);
    
}
package com.zlc.multithreading.service;

import com.zlc.multithreading.constance.TaskConstance;
import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;
import org.springframework.stereotype.Service;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 15:09
 **/
@Service
public class TestServiceTwoImpl implements TestServiceTwo {
    
    @Override
    public TaskResponseModel testTwo(String key, RequestObjectModel requestObjectModel) {
        TaskResponseModel taskResponseModel = new TaskResponseModel();
        // 测试二的处理流程
        long startTime = System.currentTimeMillis();
        try {
            // 让这个任务休眠600毫秒
            Thread.sleep(600);
        } catch (InterruptedException e) {
            e.printStackTrace();
            // 根据具体业务校验或者是处理或者该任务抛出异常的话,返回的key为error
            taskResponseModel.setKey(TaskConstance.TASK_ERROR);
            // 可以将resultCode和resultMessage统一定义一下
            // 比如说将测试一的返回码设置为1开头
            // 测试一任务异常  设置为子code为10000,对应的message为  任务一系统异常
            // 将 没通过某种规则  设置为子code为 11000, 对应的message为 没通过任务一校验规则
            // 以此类推
            taskResponseModel.setResultCode(TaskConstance.TASK_TWO_EXPECTION_CODE);
            taskResponseModel.setResultMessage("测试二任务异常啦,异常信息为:" + e.getMessage());
        }
        long endTime = System.currentTimeMillis();
        // 如果没有异常和出发不通过规则,则返回你想返回的数据,demo以返回处理时间为例
        taskResponseModel.setKey(TaskConstance.TASK_TWO_KEY);
        taskResponseModel.setResultCode(TaskConstance.TASK_SUCCESS_CODE);
        taskResponseModel.setResultMessage("测试二任务处理时间为:" + (endTime-startTime) + "毫秒");
        return taskResponseModel;
    }
}

3) Test Service Three

package com.zlc.multithreading.service;

import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 14:31
 **/
public interface TestServiceThree {
    
    TaskResponseModel testThree(String key, RequestObjectModel requestObjectModel);
}

package com.zlc.multithreading.service;

import com.zlc.multithreading.constance.TaskConstance;
import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;
import org.springframework.stereotype.Service;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 15:11
 **/
@Service
public class TestServiceThreeImpl implements TestServiceThree {
    
    @Override
    public TaskResponseModel testThree(String key, RequestObjectModel requestObjectModel) {
        TaskResponseModel taskResponseModel = new TaskResponseModel();
        // 测试三的处理流程
        long startTime = System.currentTimeMillis();
        try {
            // 让这个任务休眠300毫秒
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
            // 根据具体业务校验或者是处理或者该任务抛出异常的话,返回的key为error
            taskResponseModel.setKey(TaskConstance.TASK_ERROR);
            // 可以将resultCode和resultMessage统一定义一下
            // 比如说将测试一的返回码设置为1开头
            // 测试一任务异常  设置为子code为10000,对应的message为  任务一系统异常
            // 将 没通过某种规则  设置为子code为 11000, 对应的message为 没通过任务一校验规则
            // 以此类推
            taskResponseModel.setResultCode(TaskConstance.TASK_THREE_EXPECTION_CODE);
            taskResponseModel.setResultMessage("测试三任务异常啦,异常信息为:" + e.getMessage());
        }
        long endTime = System.currentTimeMillis();
        // 如果没有异常和出发不通过规则,则返回你想返回的数据,demo以返回处理时间为例
        taskResponseModel.setKey(TaskConstance.TASK_THREE_KEY);
        taskResponseModel.setResultCode(TaskConstance.TASK_SUCCESS_CODE);
        taskResponseModel.setResultMessage("测试三任务处理时间为:" + (endTime-startTime) + "毫秒");
        return taskResponseModel;
    }
}

4) Test Service Four

package com.zlc.multithreading.service;

import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 14:32
 **/
public interface TestServiceFour {
    
    TaskResponseModel testFour(String key, RequestObjectModel requestObjectModel);
}

package com.zlc.multithreading.service;

import com.zlc.multithreading.constance.TaskConstance;
import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;
import org.springframework.stereotype.Service;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 15:13
 **/
@Service
public class TestServiceFourImpl implements TestServiceFour {
    
    @Override
    public TaskResponseModel testFour(String key, RequestObjectModel requestObjectModel) {
        TaskResponseModel taskResponseModel = new TaskResponseModel();
        // 测试四的处理流程
        long startTime = System.currentTimeMillis();
        try {
            // 让这个任务休眠800毫秒
            Thread.sleep(800);
        } catch (InterruptedException e) {
            e.printStackTrace();
            // 根据具体业务校验或者是处理或者该任务抛出异常的话,返回的key为error
            taskResponseModel.setKey(TaskConstance.TASK_ERROR);
            // 可以将resultCode和resultMessage统一定义一下
            // 比如说将测试一的返回码设置为1开头
            // 测试一任务异常  设置为子code为10000,对应的message为  任务一系统异常
            // 将 没通过某种规则  设置为子code为 11000, 对应的message为 没通过任务一校验规则
            // 以此类推
            taskResponseModel.setResultCode(TaskConstance.TASK_FOUR_EXPECTION_CODE);
            taskResponseModel.setResultMessage("测试四任务异常啦,异常信息为:" + e.getMessage());
        }
        long endTime = System.currentTimeMillis();
        // 如果没有异常和出发不通过规则,则返回你想返回的数据,demo以返回处理时间为例
        taskResponseModel.setKey(TaskConstance.TASK_FOUR_KEY);
        taskResponseModel.setResultCode(TaskConstance.TASK_SUCCESS_CODE);
        taskResponseModel.setResultMessage("测试二任务处理时间为:" + (endTime-startTime) + "毫秒");
        return taskResponseModel;
    }
}

6, to achieve a Callable create four test task, method call needs to be rewritten, there is a return value, the task set key, request parameters, and service specific business processes;
1) a task

package com.zlc.multithreading.callback;

import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;
import com.zlc.multithreading.service.TestServiceOne;

import java.util.concurrent.Callable;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 14:38
 **/
public class TestOneCallBack implements Callable<TaskResponseModel> {
    
    private String key;
    private RequestObjectModel requestObjectModel;
    private final TestServiceOne testServiceOne;

    public TestOneCallBack(String key, RequestObjectModel requestObjectModel, TestServiceOne testServiceOne) {
        this.setKey(key);
        this.setRequestObjectModel(requestObjectModel);
        this.testServiceOne = testServiceOne;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public RequestObjectModel getRequestObjectModel() {
        return requestObjectModel;
    }

    public void setRequestObjectModel(RequestObjectModel requestObjectModel) {
        this.requestObjectModel = requestObjectModel;
    }

    @Override
    public TaskResponseModel call() {
        return testServiceOne.testOne(key,requestObjectModel);
    }
}

2) Task II

package com.zlc.multithreading.callback;

import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;
import com.zlc.multithreading.service.TestServiceTwo;

import java.util.concurrent.Callable;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 14:38
 **/
public class TestTwoCallBack implements Callable<TaskResponseModel> {
    
    private String key;
    private RequestObjectModel requestObjectModel;
    private final TestServiceTwo testServiceTwo;

    
    public TestTwoCallBack(String key, RequestObjectModel requestObjectModel, TestServiceTwo testServiceTwo) {
        this.setKey(key);
        this.setRequestObjectModel(requestObjectModel);
        this.testServiceTwo = testServiceTwo;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public RequestObjectModel getRequestObjectModel() {
        return requestObjectModel;
    }

    public void setRequestObjectModel(RequestObjectModel requestObjectModel) {
        this.requestObjectModel = requestObjectModel;
    }

    @Override
    public TaskResponseModel call() {
        return testServiceTwo.testTwo(key,requestObjectModel);
    }
}

3) Task three

package com.zlc.multithreading.callback;

import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;
import com.zlc.multithreading.service.TestServiceThree;

import java.util.concurrent.Callable;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 14:38
 **/
public class TestThreeCallBack implements Callable<TaskResponseModel> {
    
    private String key;
    private RequestObjectModel requestObjectModel;
    private final TestServiceThree testServiceThree;

    public TestThreeCallBack(String key, RequestObjectModel requestObjectModel, TestServiceThree testServiceThree) {
        this.setKey(key);
        this.setRequestObjectModel(requestObjectModel);
        this.testServiceThree = testServiceThree;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public RequestObjectModel getRequestObjectModel() {
        return requestObjectModel;
    }

    public void setRequestObjectModel(RequestObjectModel requestObjectModel) {
        this.requestObjectModel = requestObjectModel;
    }

    @Override
    public TaskResponseModel call() {
        return testServiceThree.testThree(key,requestObjectModel);
    }
}

4) Task four

package com.zlc.multithreading.callback;

import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;
import com.zlc.multithreading.service.TestServiceFour;

import java.util.concurrent.Callable;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 14:38
 **/
public class TestFourCallBack implements Callable<TaskResponseModel> {
    
    private String key;
    private RequestObjectModel requestObjectModel;
    private final TestServiceFour testServiceFour;

    public TestFourCallBack(String key, RequestObjectModel requestObjectModel, TestServiceFour testServiceFour) {
        this.setKey(key);
        this.setRequestObjectModel(requestObjectModel);
        this.testServiceFour = testServiceFour;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public RequestObjectModel getRequestObjectModel() {
        return requestObjectModel;
    }

    public void setRequestObjectModel(RequestObjectModel requestObjectModel) {
        this.requestObjectModel = requestObjectModel;
    }

    @Override
    public TaskResponseModel call() {
        return testServiceFour.testFour(key,requestObjectModel);
    }
}

7, create a Controller call it TestController

package com.zlc.multithreading.controller;

import com.zlc.multithreading.callback.TestFourCallBack;
import com.zlc.multithreading.callback.TestOneCallBack;
import com.zlc.multithreading.callback.TestThreeCallBack;
import com.zlc.multithreading.callback.TestTwoCallBack;
import com.zlc.multithreading.model.RequestObjectModel;
import com.zlc.multithreading.model.TaskResponseModel;
import com.zlc.multithreading.service.TestServiceFour;
import com.zlc.multithreading.service.TestServiceOne;
import com.zlc.multithreading.service.TestServiceThree;
import com.zlc.multithreading.service.TestServiceTwo;
import com.zlc.multithreading.task.TaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

/**
 * @author : 追到乌云的尽头找太阳-(Jacob)
 * @date : 2020/1/21 14:59
 **/
@RestController
public class TestController {
    
    private final TestServiceOne testServiceOne;
    private final TestServiceTwo testServiceTwo;
    private final TestServiceThree testServiceThree;
    private final TestServiceFour testServiceFour;
    private final TaskExecutor taskExecutor;

    public TestController(TestServiceOne testServiceOne, TestServiceTwo testServiceTwo, 
                          TestServiceThree testServiceThree, TestServiceFour testServiceFour,
                          TaskExecutor taskExecutor) {
        this.testServiceOne = testServiceOne;
        this.testServiceTwo = testServiceTwo;
        this.testServiceThree = testServiceThree;
        this.testServiceFour = testServiceFour;
        this.taskExecutor = taskExecutor;
    }

    @GetMapping(value = "testTask")
    public void testTask(){
        // 将并发任务填入,准备执行
        List<Callable<TaskResponseModel>> baseTaskCallbackList = new ArrayList<>(4);
        // 添加测试一任务
        baseTaskCallbackList.add(this.testOne());
        // 添加测试二任务
        baseTaskCallbackList.add(this.testTwo());
        //  添加测试三任务
        baseTaskCallbackList.add(this.testThree());
        // 添加测试四任务
        baseTaskCallbackList.add(this.testFour());
        // 执行任务,任务执行根据每个任务实际执行结束的时间返回,也就是说没有固定先后顺序
        List<TaskResponseModel> taskResponseModels = taskExecutor.execute(baseTaskCallbackList);
        // 查看每个任务的执行结果
        for (TaskResponseModel responseModel: taskResponseModels){
            // 看打印结果就可以发现,不管添加任务的先后顺序,哪个任务先执行完,就先返回
            // 如果任务抛出异常或者没有通过任务规则,则通过设置key来表示任务失败
            // 任务失败原因通过resultCode和resultMessage来说明
            System.out.println(responseModel);
        }
    }
    private TestOneCallBack testOne(){
        String key = "TestOne";
        RequestObjectModel requestObjectModel = new RequestObjectModel();
        return new TestOneCallBack(key, requestObjectModel, this.testServiceOne);
    }
    private TestTwoCallBack testTwo(){
        String key = "TestTwo";
        RequestObjectModel requestObjectModel = new RequestObjectModel();
        return new TestTwoCallBack(key, requestObjectModel, this.testServiceTwo);
    }
    private TestThreeCallBack testThree(){
        String key = "TestThree";
        RequestObjectModel requestObjectModel = new RequestObjectModel();
        return new TestThreeCallBack(key, requestObjectModel, this.testServiceThree);
    }
    private TestFourCallBack testFour(){
        String key = "TestFour";
        RequestObjectModel requestObjectModel = new RequestObjectModel();
        return new TestFourCallBack(key, requestObjectModel, this.testServiceFour);
    }
    
}

Fourth, the test

After starting the project in the browser or by calling at POSTMAN Controller interface you can get the results of the test results as shown below:
Here Insert Picture Description

Fifth, both here, and sweep the yard to look at micro-channel public, will not it, your support is my greatest encouragement!

Here Insert Picture Description

Published 65 original articles · won praise 48 · Views 140,000 +

Guess you like

Origin blog.csdn.net/chen15369337607/article/details/104067759