一.作用概述
- 异步计算。我每天早晨起来都有很多事情要做:洗漱-煮鸡蛋-吃早餐-等等。我的步骤是起床后先煮鸡蛋,定时10分钟,再去洗漱,等我洗漱完毕在看鸡蛋是否煮好了,煮好了就开始吃早餐,没煮好则等一会。我们把洗漱完毕在煮鸡蛋叫做同步执行,把边煮鸡蛋边洗漱叫异步执行。
- 异步体现之处(看源码):客户端把FutureTask当做一个线程去执行时,会触发FutureTask的run()方法,这个时候就已经开始计算结果了;等客户端调用get()方法时候,这个结果已经计算好就把这个结果返回,没计算好get()方法阻塞。
二.UML
三.源码分析
- Future,代表异步计算的结果,5个抽象方法顾名思义。
- Runnable,线程接口,无返回值。
- Callable,代表有返回值的一个任务。
- RunnableFuture,组合了两个接口而已。
- FutureTask,实现异步计算的地方。
package java.util.concurrent; import java.util.concurrent.locks.*; //实例化FutureTask时实例化Sync public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); sync = new Sync(callable); } //实例化FutureTask时 //1.Executors.callable内部采用适配器模式适配出一个Callable对象 //2.实例化Sync public FutureTask(Runnable runnable, V result) { sync = new Sync(Executors.callable(runnable, result)); } //以下方法基本都是委托sync对象去实现 public boolean isCancelled() { return sync.innerIsCancelled(); } public boolean isDone() { return sync.innerIsDone(); } public boolean cancel(boolean mayInterruptIfRunning) { return sync.innerCancel(mayInterruptIfRunning); } public V get() throws InterruptedException, ExecutionException { return sync.innerGet(); } public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return sync.innerGet(unit.toNanos(timeout)); } protected void done() { } protected void set(V v) { sync.innerSet(v); } protected void setException(Throwable t) { sync.innerSetException(t); } //FutureTask实现了Runnable接口,当run()方法被执行的时候 public void run() { sync.innerRun(); } protected boolean runAndReset() { return sync.innerRunAndReset(); } }
- Sync类是异步计算被委托的地方,真正实现异步计算的地方。
private final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -7828117401763700385L; /** State value representing that task is running */ private static final int RUNNING = 1; /** State value representing that task ran */ private static final int RAN = 2; /** State value representing that task was cancelled */ private static final int CANCELLED = 4; /** The underlying callable */ private final Callable<V> callable; /** The result to return from get() */ private V result; /** The exception to throw from get() */ private Throwable exception; private volatile Thread runner; ...... V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException { if (!tryAcquireSharedNanos(0, nanosTimeout)) throw new TimeoutException(); if (getState() == CANCELLED) throw new CancellationException(); if (exception != null) throw new ExecutionException(exception); return result; //返回result } void innerSet(V v) { for (;;) { int s = getState(); if (s == RAN) return; if (s == CANCELLED) { // aggressively release to set runner to null, // in case we are racing with a cancel request // that will try to interrupt runner releaseShared(0); return; } if (compareAndSetState(s, RAN)) { result = v; //将callable.call()的结果赋值给result releaseShared(0); done(); return; } } } ...... //FutureTask的run方法被执行时 void innerRun() { if (!compareAndSetState(0, RUNNING)) return; try { runner = Thread.currentThread(); if (getState() == RUNNING) // recheck after setting thread innerSet(callable.call()); //调用了callable.call() else releaseShared(0); // cancel } catch (Throwable ex) { innerSetException(ex); } } }
补充一个类Executors.RunnableAdapter,将一个Runnable对象适配成一个Callable对象,显然result为空。所以可以说Runnable是一个没有返回值的Callable。
static final class RunnableAdapter<T> implements Callable<T> { final Runnable task; final T result; RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } public T call() { task.run(); return result; } }
四.煮鸡蛋代码
package com.zzy.future; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; public class CookEgg { public static void main(String[] args) throws InterruptedException, ExecutionException { //1.煮鸡蛋 System.out.println("开始煮鸡蛋"); FutureTask<Egg> task = new FutureTask<Egg>(new EggCallable()); ExecutorService service = Executors.newSingleThreadExecutor(); service.execute(task); //2.洗漱8分钟 Thread.sleep(1000 * 8L); System.out.println("洗漱完毕"); System.out.println("鸡蛋煮熟没: " + task.isDone()); System.out.println(task.get().isHasCooked()); } } class EggCallable implements Callable<Egg> { @Override public Egg call() throws Exception { Thread.sleep(1000 * 10L); //鸡蛋煮10分钟 return new Egg(true); } } class Egg { private boolean hasCooked; public Egg(boolean hasCooked) { this.hasCooked = hasCooked; } public boolean isHasCooked() { return hasCooked; } }
相关推荐
10. **并发工具类(Concurrent Utilities)**:Java 1.5引入了`java.util.concurrent`包,提供了线程安全的数据结构和高级并发工具,如`ExecutorService`、`Future`和`Callable`等,极大地简化了多线程编程。...
最后,Java并发库还包含了很多其他有用的工具,如Semaphore(信号量)用于控制同时访问特定资源的线程数量,CyclicBarrier(循环屏障)和CountDownLatch(计数器门锁)用于多线程间的协作,以及Lock接口及其实现如...
9. **并发工具类(java.util.concurrent)**:Java 5.0引入了并发包,包含如`ExecutorService`, `Future`, `Semaphore`, `CyclicBarrier`, `CountDownLatch`等工具类,提高了多线程编程的效率和可管理性。...
《深入学习:Java多线程编程》是一本专注于Java并发技术的专业书籍,旨在帮助开发者深入理解和熟练运用Java中的多线程编程。Java多线程是Java编程中的核心部分,尤其在现代高性能应用和分布式系统中不可或缺。理解并...
### Java多线程编程大总结 #### 一、Java多线程编程的演进与重要性 Java多线程编程自Java 5之后经历了显著的革新与扩展,引入了强大的并发包,极大地增强了多线程编程的能力。在Java 5之前,多线程的支持较为薄弱...
#### 三、多线程间的同步机制 在多线程环境中,线程之间的数据共享和通信是非常重要的。为了保证数据的一致性和安全性,Java提供了多种同步机制来实现线程间的安全通信: - **`synchronized`关键字**:这是Java中...
《Java并发编程:设计原则与模式(第二版)》是一本深入探讨Java多线程编程技术的权威著作。这本书详细阐述了在Java平台中进行高效并发处理的关键概念、设计原则和实用模式。以下是对该书内容的一些核心知识点的概述...
《Java并发编程:设计原则与模式(第二版)》是一本深入探讨Java平台上的多线程和并发编程的著作。本书旨在帮助开发者理解和掌握在Java环境中进行高效并发处理的关键技术与设计模式。以下是对该书内容的一些核心知识...
另外,Java并发API(java.util.concurrent包)提供了一系列高级并发工具,如`ConcurrentHashMap`(线程安全的哈希映射)、`BlockingQueue`(阻塞队列)和`Future`(异步计算结果)。这些工具可以帮助开发者更好地...
Java多线程与并发是Java开发中的重要领域,尤其在现代高性能应用中,对多核处理器的充分利用和高效系统设计离不开并发...通过深入学习这两本书籍,开发者可以更深入地理解Java并发编程,并提升解决复杂并发问题的能力。
Java并发编程是Java开发中的重要领域,特别是在高并发、高性能的应用场景中不可或缺。并发编程能够有效地利用多核处理器资源,提高程序的运行效率,优化系统性能。以下将详细阐述Java并发编程的一些关键知识点。 ...
在Java编程中,多线程是并发处理任务的关键技术,特别是在高性能、高并发的应用场景下。本篇将探讨“多线程结果组装”的主题,它涉及到如何在多个并发执行的任务完成后,有效地收集并整合这些任务的结果。这个过程...
通过以上方法,我们可以在Java中有效地利用多线程处理数据库数据,提高程序的并发能力和效率。记得在设计时充分考虑线程间的协作与同步,以及数据库连接的管理和优化,以确保程序的稳定性和性能。
(注意,本资源附带书中源代码可供参考) 多线程与并发处理是程序设计好坏优劣的重要课题,本书通过浅显易懂的文字与实例来介绍Java线程相关的设计模式概念,并且通过实际的Java程序范例和 UML图示来一一解说,书中...
【JAVA多线程总结】 Java 多线程是Java编程中的关键特性,它允许程序同时执行多个任务,提高系统的效率和响应性。本篇总结涵盖了Java多线程的基础概念、创建与启动、线程调度、同步与协作以及新特性。 **一、Java...
配合`JAVA多线程总结.ppt`,你可以得到一个更直观和简洁的概览,快速回顾和掌握上述关键知识点。虽然中文版翻译可能存在不足,但原版英文书籍通常能更准确地传达作者的意图和细节,值得深入阅读。
在Java编程领域,并发编程是一项核心技能,尤其是在大型系统或分布式应用中,高效地处理多线程和并发操作是至关重要的。"Java并发编程与实践"文档深入剖析了这一主题,旨在帮助开发者理解和掌握如何在Java环境中有效...
《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...
5. **J.U.C框架**:Java并发 utilities (J.U.C) 框架是Java并发编程的重要组成部分,书中会介绍如何利用这个框架来提升并发性能和代码的可读性。 6. **性能调优**:在高并发场景下,性能优化是必不可少的。可能涵盖...
此外,Java 5引入了`java.util.concurrent`包,包含如`ExecutorService`, `Future`, `Callable`, `Semaphore`, `CyclicBarrier`, `CountDownLatch`等高级并发工具类,这些工具极大地简化了多线程编程。 在并发编程...