一个主线程下有多个子线程任务,主线程必须在100秒内将子线程执行的集合结果进行处理返回

个人记录: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

你可能感兴趣的:(Java技术专家)