JAVA多线程解惑之多线程返回值

如果有人问题你,多线程可以有返回值吗?你怎么回答?

 

看下面例子,我定义了一个类实现了Callable 接口

 

Java代码  收藏代码
  1. public class MyCallable implements Callable<Object> {  
  2.     @Override  
  3.     public Object call() throws Exception {  
  4.         int i=10;  
  5.         Thread.sleep(10000);  
  6.         return i;  
  7.     }  
  8.   
  9. }  

 

Callable如果要想得到返回值需要通过一个叫FutureTask的类帮助。简单的做法是这样的

 

 

Java代码  收藏代码
  1. public void test1() {  
  2.         try {  
  3.             FutureTask<Object> task = new FutureTask<Object>(new MyCallable());  
  4.             new Thread(task).start();  
  5.             System.out.println("task return : " + task.get().toString());  
  6. //get方法会一直阻塞,直到这个线程也就是call方法执行完毕  
  7. //可以通过调用isDone()来异步的询问是否已经完成。  
  8.         } catch (InterruptedException e) {  
  9.             e.printStackTrace();  
  10.         } catch (ExecutionException e) {  
  11.             e.printStackTrace();  
  12.         }  
  13.     }  

 

还有另外一种方式可以使用

Java代码  收藏代码
  1. public void test2(){  
  2.     ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();  
  3.   
  4.     Future<Object> future = newCachedThreadPool.submit(new MyCallable());  
  5.     try {  
  6.         //同样可以通过future.isDone()来异步的知道线程是否已经处理完毕  
  7.         System.out.println(future.get().toString());  
  8.     }catch (Exception e) {  
  9.         e.printStackTrace();  
  10.     } finally {  
  11.         newCachedThreadPool.shutdown();  
  12.     }  
  13. }  

 

通过上面的例子,我们知道了可以通过callable得到一个线程的返回值了,那么使用callable算多线程吗?

其实第一个例子的一行代码已经暴露出他有多线程的特性了

Java代码  收藏代码
  1. new Thread(task).start();  

 看看这个task是什么的东西

Java代码  收藏代码
  1. public class FutureTask implements RunnableFuture  
  2. //是RunnableFuture的一个实现  
  3. public interface RunnableFuture extends Runnable, Future  
  4. //是Runnable 的子接口,这就是为什么可以放入Thread类中  
  5. // 同时他又有future的特性,得到返回值  

 为了彻底看清Future到底有什么,下面接口就是Future的完整定义了

Java代码  收藏代码
  1. public interface Future  
  2. {  
  3.   
  4.     public abstract boolean cancel(boolean flag);  
  5.   
  6.     public abstract boolean isCancelled();  
  7.   
  8.     public abstract boolean isDone();  
  9.   
  10.     public abstract Object get()  
  11.         throws InterruptedException, ExecutionException;  
  12.   
  13.     public abstract Object get(long l, TimeUnit timeunit)  
  14.         throws InterruptedException, ExecutionException, TimeoutException;  
  15. }  

 现在知道了Callable是借助Runnable来实现多线程的功能,所以说它是多线程也说的过去。那么它是如何获得返回值的呢?

我们都知道线程的启动方法是start方法,然后线程内部调用了run()方法

Java代码  收藏代码
  1. public void run()  
  2. {  
  3.     sync.innerRun();  
  4. }  
  5.   
  6. protected void set(Object obj)  
  7. {  
  8.     sync.innerSet(obj);  
  9. }  
  10.   
  11. public Object get()  
  12.     throws InterruptedException, ExecutionException  
  13. {  
  14.     return sync.innerGet();  
  15. }  

 我们的调用都深入到了sync的方面里面去了。接下来

Java代码  收藏代码
  1. void innerRun()  
  2.  {  
  3.      if(!compareAndSetState(01))  
  4.          return;  
  5.      runner = Thread.currentThread();  
  6.      if(getState() == 1)  
  7.      {  
  8.          Object obj;  
  9.          try  
  10.          {  
  11.              obj = callable.call(); //这时候调用我们覆写的call方法了  
  12.          }  
  13.          catch(Throwable throwable)  
  14.          {  
  15.              setException(throwable);  
  16.              return;  
  17.          }  
  18.          set(obj);//执行完之后将结果放入存起来  
  19.      } else  
  20.      {  
  21.          releaseShared(0);  
  22.      }  
  23.  }  

如何存,很简单,存入事先准备好的属性中

Java代码  收藏代码
  1. void innerSet(Object obj)  
  2.         {  
  3.             int i;  
  4.             do  
  5.             {  
  6.                 i = getState();  
  7.                 if(i == 2)  
  8.                     return;  
  9.                 if(i == 4)  
  10.                 {  
  11.                     releaseShared(0);  
  12.                     return;  
  13.                 }  
  14.             } while(!compareAndSetState(i, 2));  
  15.             result = obj;//这么存的  
  16.             releaseShared(0);  
  17.             done();  
  18.         }  

 如何取

Java代码  收藏代码
    1. Object innerGet()  
    2.     throws InterruptedException, ExecutionException  
    3. {  
    4.     acquireSharedInterruptibly(0);  
    5.     if(getState() == 4)  
    6.         throw new CancellationException();  
    7.     if(exception != null)  
    8.         throw new ExecutionException(exception);  
    9.     else  
    10.         return result; 
posted @ 2014-03-07 15:22  逍遥_时空  阅读(1809)  评论(0编辑  收藏  举报