天天看点

Java ExecutorService 多线程 | 使用线程池 批量处理 通用效验 看题:解题:

目录

看题:

 要求:

解题:

先创建 三个 实体类。

ok,   此时需要对字段处理 效验,并有相应提示。

ok,接下来使用多线程批量处理。

ok,测试

输出结果

老司机开车,飙车有炫酷。多么迷人的idea。放张图镇镇场面。

Java ExecutorService 多线程 | 使用线程池 批量处理 通用效验 看题:解题:

看题:

Java ExecutorService 多线程 | 使用线程池 批量处理 通用效验 看题:解题:

备注:学生类 与 地址类 为一对一,学生类 与 电子产品类 为一对多。

 要求:

多线程批量校验100多名学生信息,但是校验的方法每次只能同时校验5名学生。要求这一百多名学生信息的校验结果同时返回到校验结果展示页面。校验结果展示模板为:XXX字段不能为空!(校验一个类时,只要遇到必填校验不通过,就可返回,不必继续校验完剩余字段)

写的时候,尽量把校验方法写成适用于各种类的通用方法。不要硬编码。

解题:

先创建 三个 实体类。

Address
           
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * 地址类
 *
 * @author wbw
 * @date 2019/7/19 9:29
 */
@Data
@Accessors(chain = true)
public class Address implements Serializable {
    /**
     * 地区
     */
    private String provence;
    /**
     * 城市
     */
    private String city;
    /**
     * 下级
     */
    private String down;
}
           
Electronic
           
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * 电子产品类
 *
 * @author wbw
 * @date 2019/7/19 9:28
 */
@Data
@Accessors(chain = true)
public class Electronic implements Serializable {

    private Integer id;

    private String name;

    private String color;
}
           
Student
           
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.List;

/**
 * 学生类
 *
 * @author wbw
 * @date 2019/7/19 9:25
 */
@Data
@Accessors(chain = true)
public class Student implements Serializable {
    /**
     * id
     */
    private Long cardId;
    /**
     * 名称
     */
    private String name;
    /**
     * 性别
     */
    private String sex;
    /**
     * 电子产品类
     */
    private List<Electronic> electronics;
    /**
     * 地址
     */
    private Address address;

}
           

所需要的 pom

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
           

ok,  此时需要对字段处理 效验,并有相应提示。

考虑可以使用 map 前面为字段名称,后面为字段的值。我这里用了json。

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.jayway.jsonpath.JsonPath;
import lombok.Getter;

import java.util.stream.Stream;

/**
 * 通用效验
 *
 * @author wbw
 * @date 2019/7/19 12:42
 */
@Getter
class ValidCommon {

    private String msg;

    private static final String TEMPLATE_2 = "字段 %s.%s 效验通过....";
    private static final String TEMPLATE_1 = "字段 %s.%s 效验未通过....";

    /**
     * 是否为真
     *
     * @param obj 参数
     * @author wbw
     * @date 12:46 2019/7/19
     */
    private boolean toValidFlag(Object... obj) {
        if (ObjectUtil.isEmpty(obj)) {
            return true;
        }
        for (Object o : obj) {
            if (ObjectUtil.isEmpty(o)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检查字段的值是否有效
     *
     * @param field 检查的字段
     * @param clazz 对象
     * @return boolean
     * @author wbw
     * @date 14:03 2019/7/19
     */
    boolean checkField(Object clazz, Object... field) {
        if (toValidFlag(field)) {
            return true;
        }
        String json = JSONUtil.parse(clazz).toJSONString(2);
        String className = clazz.getClass().getSimpleName();
        return Stream.of(field).anyMatch((x) -> {
            if (toValidFlag(x)) {
                msg = String.format(TEMPLATE_1, className, x);
                return true;
            }
            try {
                if (toValidFlag(JsonPath.parse(json).read("$." + x).toString())) {
                    msg = String.format(TEMPLATE_1, className, x);
                    return true;
                }
            } catch (Exception e) {
                msg = String.format(TEMPLATE_1, className, x);
                return true;
            }
            msg = String.format(TEMPLATE_2, className, x);
            return false;
        });
    }
}
           

 所需要的pom

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.4.0</version>
</dependency>

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>4.5.16</version>
</dependency>
           

ok,接下来使用多线程批量处理。

这里使用了 ExecutorService 线程池,注意,在执行完毕的时候,子线程和主线程是异步的,所以要等待子线程执行完毕,切记。

pool.awaitTermination(awaitMaxTimeMs, TimeUnit.MILLISECONDS)
           
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.hb.myproject.thread.entity.Address;
import com.hb.myproject.thread.entity.Electronic;
import com.hb.myproject.thread.entity.Student;
import lombok.extern.log4j.Log4j2;

import java.util.*;
import java.util.concurrent.*;


/**
 * 批量处理
 *
 * @author wbw
 * @date 2019/7/19 9:36
 */
@Log4j2
public class BatchProcessing {

    private ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
            .setNameFormat(BatchProcessing.class.getName() + "-pool-%d").build();
    private ExecutorService pool = new ThreadPoolExecutor(5, 5,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

    /**
     * 批量处理
     *
     * @param student 多个学生信息
     * @return key 为id信息,value 为输出结果
     * @author wbw
     * @date 9:50 2019/7/19
     */
    public Map<Student, String> desiredResult(List<Student> student) {
        if (student == null || student.size() < 1) {
            log.info("无数据处理....");
            return new HashMap<>(0);
        }
        final Map<Student, String> map = new ConcurrentHashMap<>(student.size());
        student.forEach(stu -> pool.execute(() -> verifyStu(stu, map)));
        this.shutdown();
        return map;
    }

    /**
     * 执行线程完成
     *
     * @author wbw
     * @date 15:46 2019/7/19
     */
    public void shutdown() {
        pool.shutdown();
        try {
            int awaitMaxTimeMs = 3000;
            if (!pool.awaitTermination(awaitMaxTimeMs, TimeUnit.MILLISECONDS)) {
                // 超时的时候向线程池中所有的线程发出中断(interrupted)。
                pool.shutdownNow();
            }
        } catch (InterruptedException e) {
            log.error(e);
        }
    }

    /**
     * 验证
     *
     * @param stu 处理信息
     * @param map 结果存储
     * @return boolean
     * @author wbw
     * @date 10:29 2019/7/19
     */
    private void verifyStu(Student stu, Map<Student, String> map) {
        ValidCommon valid = new ValidCommon();
        if (valid.checkField(stu, "cardId", "name", "electronics", "address")) {
            map.put(stu, valid.getMsg());
            return;
        }

        List<Electronic> electronics = stu.getElectronics();
        for (Electronic electronic : electronics) {
            if (valid.checkField(electronic, "id", "name")) {
                map.put(stu, valid.getMsg());
                return;
            }
        }

        Address address = stu.getAddress();
        if (valid.checkField(address, "city", "down")) {
            map.put(stu, valid.getMsg());
            return;
        }
        map.put(stu, valid.getMsg());
    }


}
           

所需要的pom

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>27.0.1-jre</version>
</dependency>
           

ok,测试

import cn.hutool.json.JSONUtil;
import com.hb.myproject.thread.entity.Address;
import com.hb.myproject.thread.entity.Electronic;
import com.hb.myproject.thread.entity.Student;
import com.hb.myproject.thread.local.BatchProcessing;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author wbw
 * @date 2019/7/19 13:44
 */
public class Test {


    public static void main(String[] args) {
        BatchProcessing batchProcessing = new BatchProcessing();
        List<Student> students = new LinkedList<>();
        for (int i = 0; i < 1000; i++) {
            Student student = new Student();
            Address address = new Address();
            if (i % 3 == 2) {
                address.setCity("xxxaxa" + i).setProvence("gw33wg" + i).setDown("fewgfew" + i);
            }
            student.setAddress(address).setCardId(i + 45L).setName("xxxx" + i);
            List<Electronic> electronics = new LinkedList<>();
            for (int j = 0; j < 10; j++) {
                Electronic electronic = new Electronic();
                electronic.setColor("red" + j).setId(j).setName("xxaxsqf" + j);
                electronics.add(electronic);
            }
            student.setElectronics(electronics);
            students.add(student);
        }

        Map<Student, String> studentStringMap = batchProcessing.desiredResult(students);

        System.out.println(studentStringMap.size());
        System.out.println(JSONUtil.parse(studentStringMap).toJSONString(2));
    }
}
           

输出结果

Java ExecutorService 多线程 | 使用线程池 批量处理 通用效验 看题:解题: