读书笔记-java并发编程-核心方法与框架6-10

第六章 CompletionService的使用

接口CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,这样可以将执行任务与处理任务分离开来进行处理。使用submit执行任务,使用take取得已完成的任务,并按照完成这些任务的时间顺序处理它们的结果。

	public static void main(String[] args) {
		try {
			MyCallable callable1 = new MyCallable("username1", 5000);
			MyCallable callable2 = new MyCallable("username2", 4000);
			MyCallable callable3 = new MyCallable("username3", 3000);
			MyCallable callable4 = new MyCallable("username4", 2000);
			MyCallable callable5 = new MyCallable("username5", 1000);

			List<Callable> callableList = new ArrayList<Callable>();
			callableList.add(callable1);
			callableList.add(callable2);
			callableList.add(callable3);
			callableList.add(callable4);
			callableList.add(callable5);

			ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 5,
					TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
			CompletionService csRef = new ExecutorCompletionService(executor);

			for (int i = 0; i < 5; i++) {
				csRef.submit(callableList.get(i));
			}

			for (int i = 0; i < 5; i++) {
				System.out.println("等待打印第" + (i + 1) + "个返回值");
				System.out.println(csRef.take().get());
			}
			// 按乱序打印的效果
			// 说明一个Future对应当前先执行完的Callable任务
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}

	}

CompletionService完全解决了Future阻塞的特性,也就是使用CompletionService接口后,哪个任务先执行完,哪个任务的返回值就先打印。

  • 方法take()取得最先完成任务的Future对象,谁执行时间最短谁最先返回。
  • 接口CompletionService完全可以避免FutureTask类阻塞的缺点,可更加有效地处理Future的返回值,也就是哪个任务先执行完,CompletionService就先取得这个任务的返回值再处理

第七章 接口ExecutorService的方法使用

  • 方法invokeAny()和invokeAll()具有阻塞特性。

第八章 计划任务ScheduledExecutorService的使用

  • 类ScheduledExecutorService的主要作用就是可以将定时任务与线程池功能结合使用。
public static void main(String[] args) {
		try {
			List<Callable> callableList = new ArrayList();
			callableList.add(new MyCallableA());
			callableList.add(new MyCallableB());
			// 调用方法newSingleThreadScheduledExecutor
			// 取得一个单任务的计划任务执行池
			ScheduledExecutorService executor = Executors
					.newSingleThreadScheduledExecutor();
			ScheduledFuture<String> futureA = executor.schedule(callableList
					.get(0), 4L, TimeUnit.SECONDS);
			ScheduledFuture<String> futureB = executor.schedule(callableList
					.get(1), 4L, TimeUnit.SECONDS);
			System.out.println("          X=" + System.currentTimeMillis());
			System.out.println("返回值A:" + futureA.get());
			System.out.println("返回值B:" + futureB.get());
			System.out.println("          Y=" + System.currentTimeMillis());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
	}
  • 使用scheduleAtFixedRate()方法实现周期性执行
  • 方法getQueue()的作用是取得队列中的任务,而这些任务是未来将要运行的,正在运行的任务不在此队列中

第九章 Fork-Join分治编程

  • 使用类RecursiveAction执行的任务是具有无返回值的,仅执行一次任务。
  • 使用类RecursiveTask执行的任务具有返回值的功能。
  • 方法join()与get()虽然都能取得计算后的结果值,但它们之间还是在出现异常时有处理上的区别,get可以直接在主线程捕获异常,join会直接抛出异常

第十章 并发集合框架

  • 类ConcurrentHashMap是支持并发操作的Map对象。
原文地址:https://www.cnblogs.com/Baronboy/p/14073659.html