问题描述:假如客户给你丢过来1000个订单,这些订单都需要1到2秒的处理时间。你怎么以最快的速度完成处理并保存到数据库?
问题解析:设每个运单处理需要1秒的时间。
-
以传统的方式去处理,我写个循环,一个订单一个订单地去处理,那么总耗时为:1*1000=1000秒(约等于17个分钟,那客户还不急死?)
-
以多线程的方式去处理,1000的个订单我就创建1000个线程去处理,那么总耗时就只有1秒!(很明显,客户喜欢这种方式)
如何实施(因为资源的问题,不能创建1000个线程):
我现在先假设用户丢过来13条数据,由于资源的问题我们只能创建5个线程,那么每个线程应该处理几条数据?
int per = data.size() / 5 = 2,这样一来每个线程只能处理两个,那么还剩下3个怎么办?
package org.java.test4;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class ThreadDemo {
private static class ProcessDataTask implements Callable<String> {
private List<String> data = new ArrayList<>();
public void add(String item) {
data.add(item);
}
@Override
public String call() throws Exception {
//处理数据
for (String item : data) {
System.out.println(Thread.currentThread().getName() + "-data:" + item);
}
//模拟数据处理需要1秒钟
Thread.sleep(1000);
//最后返回你想返回的东西
return Thread.currentThread().getName();
}
}
public static void main(String[] args) throws Exception {
//模拟客户数据,假设现在客户上传了13条数据
List<String> userData = new ArrayList<String>();
for (int i = 1; i <= 13; i++) {
userData.add("jackson_" + i);
}
//构造线程,假设总的线程数为5个
int totalThreadNum = 5;
List<ProcessDataTask> tasks = buildThread(userData, 5);
//构造线程池,然后执行每一个线程
ExecutorService executorService = Executors.newFixedThreadPool(totalThreadNum);
List<Future<String>> threadResults = executorService.invokeAll(tasks);
executorService.shutdown();
//遍历线程结果
for (Future<String> future : threadResults) {
try {
FutureTask<String> futureTask = (FutureTask<String>) future;
System.out.println("thread return value: " + futureTask.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 根据数据和线程数为每一个线程分配数据
* @param data
* @param totalThreadNum
* @return
* @throws Exception
*/
public static List<ProcessDataTask> buildThread(List data, int totalThreadNum) throws Exception {
int nThreads = totalThreadNum;
int perThreadDataNum = data.size() / nThreads;
int remainDataNum = data.size() % nThreads;
List<ProcessDataTask> tasks = new ArrayList<ProcessDataTask>();
for (int i = 0; i < nThreads; i++) {
ProcessDataTask processDataTask = new ProcessDataTask();
Iterator iterator = data.iterator();
int j = 0;
while (j < perThreadDataNum && iterator.hasNext()) {
processDataTask.add((String) iterator.next());
iterator.remove();
++j;
}
if (remainDataNum > 0) {
processDataTask.add((String) iterator.next());
iterator.remove();
remainDataNum--;
}
tasks.add(processDataTask);
}
return tasks;
}
}