目錄
看題:
要求:
解題:
先建立 三個 實體類。
ok, 此時需要對字段處理 效驗,并有相應提示。
ok,接下來使用多線程批量處理。
ok,測試
輸出結果
老司機開車,飙車有炫酷。多麼迷人的idea。放張圖鎮鎮場面。

看題:
備注:學生類 與 位址類 為一對一,學生類 與 電子産品類 為一對多。
要求:
多線程批量校驗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));
}
}