天天看點

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 多線程 | 使用線程池 批量處理 通用效驗 看題:解題: