个人记录:2018年,工作的第6到7个年头。
重点研究自己不太擅长的技术:分布式、高并发、大数据量、数据库优化、高性能、负载均衡等。
刷题是一种态度,是一种好习惯。
我刷题,我骄傲。
题目:一个主线程下有多个子线程任务,主线程必须在100秒内将子线程执行的集合结果进行处理返回,子线程如果在100秒内没有执行完停止执行。
写了3个例子,用Future、FutureTask、ThreadPoolExecutor、CompletionService。
例子1:
package cn.fansunion.executorservice;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
//获得Future的值,如果还没返回,就等待
public class FutureTaskTest {
public static void main(String[] args) {
// 【强制】线程池不允许使用 Executors ExecutorsExecutors
// 去创建,而是通过 去创建,而是通过 去创建,而是通过 ThreadPoolExecutor
// ThreadPoolExecutor的方式,这样 的方式,这样 的处理方式让写同学更加明确线程池运行规则,避资源耗尽风险。
int nThreads = 5;
ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(1000));
List> taskList = new ArrayList>(10);
for (int index = 1; index <= 10; index++) {
Integer num = new Random().nextInt(10);
System.out.println(String.format("index:%s,num=%s", index,num));
FutureTask task = new FutureTask<>(new Callable() {
public Integer call() throws Exception {
int maxSleepNum = 10;
Integer sleepNum = new Random().nextInt(maxSleepNum);
System.out.println(String.format("SleepNum:%s", sleepNum));
Thread.sleep(sleepNum*1000);
return num;
}
});
if(!executor.isShutdown()){
executor.submit(task);
}
taskList.add(task);
}
Integer sum = 0;
for (FutureTask task : taskList) {
try {
//阻塞,Waits if necessary for the computation to complete, and then retrieves its result.
Integer num = task.get();
System.out.println(String.format("num=%s",num));
sum += num;
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdownNow();
System.out.println(sum);
}
}
例子2:
package cn.fansunion.executorservice;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* CompletionService,先获得,最快得到结果的那个线程的值
* @author leiwen1
*
*/
public class FutureTaskTest2 {
public static void main(String[] args) {
// 【强制】线程池不允许使用 Executors ExecutorsExecutors
// 去创建,而是通过 去创建,而是通过 去创建,而是通过 ThreadPoolExecutor
// ThreadPoolExecutor的方式,这样 的方式,这样 的处理方式让写同学更加明确线程池运行规则,避资源耗尽风险。
int nThreads = 5;
ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(1000));
CompletionService completionService= new ExecutorCompletionService(executor);
int maxIndex = 10;
//List> taskList = new ArrayList>(maxIndex);
for (int index = 1; index <= maxIndex; index++) {
Integer num = new Random().nextInt(maxIndex);
System.out.println(String.format("index:%s,num=%s", index,num));
Callable callable = new Callable() {
public Integer call() throws Exception {
int maxSleepNum = 10;
Integer sleepNum = new Random().nextInt(maxSleepNum);
System.out.println(String.format("SleepNum:%s", sleepNum));
Thread.sleep(sleepNum*1000);
return num;
}
};
//Future task = new FutureTask<>(callable);
if(!executor.isShutdown()){
completionService.submit(callable);
}
}
Integer sum = 0;
for (int index = 1; index <= maxIndex; index++) {
try {
//查询最新1个完成的任务,然后删除
//Retrieves and removes the Future representing the next completed task, waiting if none are yet present.
Future future = completionService.take();
Integer num = future.get();
System.out.println(String.format("num=%s",num));
sum += num;
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdownNow();
System.out.println(sum);
}
}
在例子2的基础上,改了点,就是题目所要的效果。
例子3:
package cn.fansunion.executorservice;
import java.util.Arrays;
import java.util.Collections;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* CompletionService,先获得,最快得到结果的那个线程的值
* pool方法,可以设置超时时间
*
*/
public class FutureTaskTest3 {
public static void main(String[] args) {
// 【强制】线程池不允许使用 Executors ExecutorsExecutors
// 去创建,而是通过 去创建,而是通过 去创建,而是通过 ThreadPoolExecutor
// ThreadPoolExecutor的方式,这样 的方式,这样 的处理方式让写同学更加明确线程池运行规则,避资源耗尽风险。
int nThreads = 5;
ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(1000));
CompletionService completionService= new ExecutorCompletionService(executor);
int maxIndex = 100;
//1到100求和
for (int index = 1; index <= maxIndex; index++) {
Integer num = index;
System.out.println(String.format("index:%s,num=%s", index,num));
Callable callable = new Callable() {
public Integer call() throws Exception {
//让一部分超时
int maxSleepNum = 350;
Integer sleepNum = new Random().nextInt(maxSleepNum);
System.out.println(String.format("SleepNum:%s", sleepNum));
//模拟计算时间,比如从远程查询数据
Thread.sleep(sleepNum);
return num;
}
};
//Future task = new FutureTask<>(callable);
if(!executor.isShutdown()){
completionService.submit(callable);
}
}
//所有成功返回的num
Integer[] taskNumArray = new Integer[maxIndex];
for (int index = 1; index <= maxIndex; index++) {
try {
//等待下1个完成的任务,然后删除,但是最多等待一定的时间
Future future = completionService.poll(100, TimeUnit.MILLISECONDS);
//模拟100毫秒,方便模拟超时,程序快点执行
if(future==null){
break;
}
Integer num = future.get();
taskNumArray[index-1]=num;
System.out.println(String.format("num=%s,成功返回1个数据",num));
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdownNow();
Integer sum = 0;
//Collections.sort(Arrays.asList(taskNumArray));
//System.out.println(taskNumArray);
for(Integer num:taskNumArray){
//超时的那几个,么有值,位置是空的
if(num != null){
System.out.print(num+",");
sum+= num;
}
}
System.out.println();
System.out.println(String.format("sum=%s", sum));
}
}
输出结果(每次都是随机的):
num=53,成功返回1个数据
SleepNum:1
num=56,成功返回1个数据
SleepNum:296
num=61,成功返回1个数据
1,5,3,6,2,4,8,11,7,14,10,13,17,15,9,19,16,22,12,20,23,24,25,18,21,26,30,27,29,28,33,35,31,37,34,38,40,32,42,39,36,45,46,48,41,43,50,49,47,52,44,55,51,54,53,56,61,
sum=1657