<bean id="threadPoolTaskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<!-- 核心线程数,默认为1 -->
<property name="corePoolSize" value="5" />
<!-- 最大线程数,默认为Integer.MAX_VALUE -->
<property name="maxPoolSize" value="10" />
<!-- 队列最大长度,一般需要设置值>=notifyScheduledMainExecutor.maxNum;默认为Integer.MAX_VALUE
<property name="queueCapacity" value="1000" /> -->
<!-- 线程池维护线程所允许的空闲时间,默认为60s -->
<property name="keepAliveSeconds" value="300" />
<!-- 线程池对拒绝任务(无线程可用)的处理策略,目前只支持AbortPolicy、CallerRunsPolicy;默认为后者 -->
<property name="rejectedExecutionHandler">
<!-- AbortPolicy:直接抛出java.util.concurrent.RejectedExecutionException异常 -->
<!-- CallerRunsPolicy:主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度 -->
<!-- DiscardOldestPolicy:抛弃旧的任务、暂不支持;会导致被丢弃的任务无法再次被执行 -->
<!-- DiscardPolicy:抛弃当前任务、暂不支持;会导致被丢弃的任务无法再次被执行 -->
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
</property>
</bean>
然后定义一个component组件,然后线程的引用就十分简单了,只要把这个线程扔进这个线程池子就行了
package com.digitalpublishing.sage.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import org.springframework.stereotype.Component;
import com.digitalpublishing.module.sage.PJournal;
import com.digitalpublishing.sage.dao.AcLogCounterWebMapper;
/**
* @ClassName: CounterWebJr1
* @Description: webJr1统计数据查询
* @author wd
* @date 2018年12月26日 上午9:22:20
*
*/
@Component
public class CounterWebJr1 implements Callable< ArrayList<Object[]>> {
private AcLogCounterWebMapper acLogCounterWebMapper;
private List<PJournal> journalList;
private String accountId;
private String startTime;
private String endTime;
private List<String> dateHeader;
public void setAcLogCounterWebMapper(AcLogCounterWebMapper acLogCounterWebMapper) {
this.acLogCounterWebMapper = acLogCounterWebMapper;
}
public void setJournalList(List<PJournal> journalList) {
this.journalList = journalList;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public void setDateHeader(List<String> dateHeader) {
this.dateHeader = dateHeader;
}
@Override
public ArrayList<Object[]> call() throws Exception {
ArrayList<Object[]> rows = new ArrayList<>();
// 根据机构ID 刊ID 年月 查询对应的记录
for (PJournal journal : journalList) {
String journalId = journal.getMdcProJournalId();
// 以 年月 TYPE 分类
List<Map<String, String>> list = acLogCounterWebMapper.getLogCounterJr1(accountId, journalId, startTime,
endTime);
List<String> content = new ArrayList<>();
content.add(journal.getTitle());
content.add("SAGE Publications");
content.add("SAGE Journals");
content.add("10.1177/" + journal.getFla());
content.add(journal.getFla());
content.add(journal.getIssn());
content.add(journal.getEissn());
int total = 0;// 一个刊统计时间段内的总数
int html = 0;// 一个刊统计时间段内的html总数
int pdf = 0;// 一个刊统计时间段内的pdf总数
// 每个刊每个月的访问数
Map<String, String> mapC = new HashMap<String, String>();
if (list.isEmpty()) {
// 未查询出记录则直接赋值为0
content.add(String.valueOf(total));
content.add(String.valueOf(html));
content.add(String.valueOf(pdf));
for (int i = 0; i < dateHeader.size(); i++) {
content.add("0");
}
} else {
// 有记录的可能会存在一个月内不同TYPE的两条记录
for (Map<String, String> map : list) {
// 月份
String time = (String) map.get("LOGTIME");
// 类型 3 4
String type = map.get("TYPE");
// 访问数
String num = map.get("C");
// 刊 时间段内访问总数
total += Integer.valueOf(num);
// 刊时间段内 PDF 和 HTML 访问数 && PDF,HTML所有访问数
if ("3".equals(type)) {
pdf += Integer.valueOf(num);
}
if ("4".equals(type)) {
html += Integer.valueOf(num);
}
if (mapC.containsKey(time)) {
String val = mapC.get(time);
mapC.put(time, String.valueOf(Integer.valueOf(val) + Integer.valueOf(num)));
} else {
mapC.put(time, num);
}
}
content.add(String.valueOf(total));
content.add(String.valueOf(html));
content.add(String.valueOf(pdf));
for (String key : dateHeader) {
if (mapC.containsKey(key)) {
content.add(mapC.get(key));
} else {
content.add("0");
}
}
}
rows.add(content.toArray());
}
return rows;
}
}
最后在你所需要的地方就可以调用这个组件了,不论是service还是controller都行
List<Future<ArrayList<Object[]>>> results = new ArrayList<Future<ArrayList<Object[]>>>(10);
List<List<PJournal>> splitList = ListUtils.averageAssign(journalList, 10);
for (List<PJournal> list : splitList) {
CounterWebJr1 ct = new CounterWebJr1();
ct.setAcLogCounterWebMapper(acLogCounterWebMapper);
ct.setAccountId(accountId);
ct.setDateHeader(dateHeader);
ct.setStartTime(startTime);
ct.setEndTime(endTime);
ct.setJournalList(list);
Future<ArrayList<Object[]>> future = threadPoolTaskExecutor.submit(ct);
results.add(future);
}
for (Future<ArrayList<Object[]>> future : results) {
ArrayList<Object[]> arrayList = future.get();
rows.addAll(arrayList);
}