如果有人问题你,多线程可以有返回值吗?你怎么回答?
看下面例子,我定义了一个类实现了Callable 接口
public class MyCallable implements Callable<Object> { @Override public Object call() throws Exception { int i=10; Thread.sleep(10000); return i; } }
Callable如果要想得到返回值需要通过一个叫FutureTask的类帮助。简单的做法是这样的
public void test1() { try { FutureTask<Object> task = new FutureTask<Object>(new MyCallable()); new Thread(task).start(); System.out.println("task return : " + task.get().toString()); //get方法会一直阻塞,直到这个线程也就是call方法执行完毕 //可以通过调用isDone()来异步的询问是否已经完成。 } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
还有另外一种方式可以使用
public void test2(){ ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); Future<Object> future = newCachedThreadPool.submit(new MyCallable()); try { //同样可以通过future.isDone()来异步的知道线程是否已经处理完毕 System.out.println(future.get().toString()); }catch (Exception e) { e.printStackTrace(); } finally { newCachedThreadPool.shutdown(); } }
通过上面的例子,我们知道了可以通过callable得到一个线程的返回值了,那么使用callable算多线程吗?
其实第一个例子的一行代码已经暴露出他有多线程的特性了
new Thread(task).start();
看看这个task是什么的东西
public class FutureTask implements RunnableFuture //是RunnableFuture的一个实现 public interface RunnableFuture extends Runnable, Future //是Runnable 的子接口,这就是为什么可以放入Thread类中 // 同时他又有future的特性,得到返回值
为了彻底看清Future到底有什么,下面接口就是Future的完整定义了
public interface Future { public abstract boolean cancel(boolean flag); public abstract boolean isCancelled(); public abstract boolean isDone(); public abstract Object get() throws InterruptedException, ExecutionException; public abstract Object get(long l, TimeUnit timeunit) throws InterruptedException, ExecutionException, TimeoutException; }
现在知道了Callable是借助Runnable来实现多线程的功能,所以说它是多线程也说的过去。那么它是如何获得返回值的呢?
我们都知道线程的启动方法是start方法,然后线程内部调用了run()方法
public void run() { sync.innerRun(); } protected void set(Object obj) { sync.innerSet(obj); } public Object get() throws InterruptedException, ExecutionException { return sync.innerGet(); }
我们的调用都深入到了sync的方面里面去了。接下来
void innerRun() { if(!compareAndSetState(0, 1)) return; runner = Thread.currentThread(); if(getState() == 1) { Object obj; try { obj = callable.call(); //这时候调用我们覆写的call方法了 } catch(Throwable throwable) { setException(throwable); return; } set(obj);//执行完之后将结果放入存起来 } else { releaseShared(0); } }
如何存,很简单,存入事先准备好的属性中
void innerSet(Object obj) { int i; do { i = getState(); if(i == 2) return; if(i == 4) { releaseShared(0); return; } } while(!compareAndSetState(i, 2)); result = obj;//这么存的 releaseShared(0); done(); }
如何取
Object innerGet() throws InterruptedException, ExecutionException { acquireSharedInterruptibly(0); if(getState() == 4) throw new CancellationException(); if(exception != null) throw new ExecutionException(exception); else return result;
相关推荐
根据提供的信息,“Java解惑.pdf”是一本针对Java编程语言的书籍,主要目的是通过大量的实例来帮助读者理解和避免常见的程序缺陷及陷阱。本书不仅适用于初学者,也对有一定经验的Java程序员具有很高的参考价值。接...
这个文件可能涵盖了许多Java的高级主题,如内存管理、多线程、集合框架的高效使用、异常处理的最佳实践,甚至是JVM的内部机制。 总之,Java编程中有很多微妙而重要的细节需要注意,包括异常处理的正确使用、源码的...
Java并发程序设计是Java开发中的重要领域,尤其在多核处理器和分布式系统中,有效利用并发可以极大地提高软件...通过学习这个教程,开发者将能够编写出更加高效、安全的并发程序,以应对现代多线程和分布式环境的需求。
它具有面向对象、跨平台、多线程和安全性高等特点。Java的跨平台特性使得Java程序能够在多种操作系统上运行,这得益于Java虚拟机(JVM)的存在。Java的代码在编写完成后,需要通过Java编译器编译成字节码,然后由JVM...
- **理解掌握 Java 高级特性**:如面向对象编程、异常处理、多线程等高级主题。 - **解惑释疑 Java 难点和疑点**:针对常见的问题和困惑进行解答,帮助学员克服学习障碍。 #### 适用人群 - **Java 初学者**:适合...
8. **多线程**:学习如何创建和管理线程,理解同步与异步执行的概念。 9. **GUI编程**:使用Swing或JavaFX库创建图形用户界面,学习组件布局和事件处理。 10. **标准库与API**:熟悉Java标准库提供的各种类和方法...