• 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; 
  • 相关阅读:
    CCNP-----企业网三层架构——BCMSN
    Redis 的 GEO 特性将在 Redis 3.2 版本释出
    CentOS6.5上源码安装MongoDB3.2.1
    beanstalkd
    php7---redis
    MongoDB学习笔记(入门)
    MongoDB学习笔记(数据操作)
    MongoDB学习笔记(索引)
    CentOS 安装MongoDB
    爬虫----Web_WeChat
  • 原文地址:https://www.cnblogs.com/sand-tiny/p/3586491.html
Copyright © 2020-2023  润新知