zoukankan      html  css  js  c++  java
  • java多线Runnable接口和Callable接口

    Runnable是1.0就有了的线程接口

      不会返回结果,并且无法抛出返回结果的异常。

       Runnable 使用 run() 方法 

    Callable 是1.5新增的

      可以返回值,这个返回值可以被Future拿到, 可以抛出受检查的异常,比如ClassNotFoundException

      Callable 使用 call() 方法

    这里详细说下Callable 的使用:

    1,用FutureTask来启动线程和接收返回值

      FutureTask实现了两个接口,Runnable和Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值,那么这个组合的使用有什么好处呢?假设有一个很耗时的返回值需要计算,并且这个返回值不是立刻需要的话,那么就可以使用这个组合,用另一个线程去计算返回值,而当前线程在使用这个返回值之前可以做其它的操作,等到需要这个返回值时,再通过Future得到,岂不美哉!这里有一个Future模式的介绍:http://openhome.cc/Gossip/DesignPattern/FuturePattern.htm

      

    public class CallableAndFuture {  
        public static void main(String[] args) {  
            Callable<Integer> callable = new Callable<Integer>() {  
                public Integer call() throws Exception {  
                    return new Random().nextInt(100);  
                }  
            };  
            FutureTask<Integer> future = new FutureTask<Integer>(callable);  
            new Thread(future).start(); 
            try {  
                Thread.sleep(5000);// 可能做一些事情  
                System.out.println(future.get());  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            } catch (ExecutionException e) {  
                e.printStackTrace();  
            }  
        }  
    }  

    下面来看另一种方式使用Callable和Future,通过ExecutorService的submit方法执行Callable,并返回Future,代码如下:

    public class CallableAndFuture {  
        public static void main(String[] args) {  
            ExecutorService threadPool = Executors.newSingleThreadExecutor();  
            Future<Integer> future = threadPool.submit(new Callable<Integer>() {  
                public Integer call() throws Exception {  
                    return new Random().nextInt(100);  
                }  
            });  
            try {  
                Thread.sleep(5000);// 可能做一些事情  
                System.out.println(future.get());  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            } catch (ExecutionException e) {  
                e.printStackTrace();  
            }  
        }  
    }  

    ExecutorService继承自Executor,它的目的是为我们管理Thread对象,从而简化并发编程,Executor使我们无需显示的去管理线程的生命周期,是JDK 5之后启动任务的首选方式。

    执行多个带返回值的任务,并取得多个返回值,代码如下:

      

    public class CallableAndFuture {  
        public static void main(String[] args) {  
            ExecutorService threadPool = Executors.newCachedThreadPool();  
            CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(threadPool);  
            for(int i = 1; i < 5; i++) {  
                final int taskID = i;  
                cs.submit(new Callable<Integer>() {  
                    public Integer call() throws Exception {  
                        return taskID;  
                    }  
                });  
            }  
            // 可能做一些事情  
            for(int i = 1; i < 5; i++) {  
                try {  
                    System.out.println(cs.take().get());  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                } catch (ExecutionException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }        

      其实也可以不使用CompletionService,可以先创建一个装Future类型的集合,用Executor提交的任务返回值添加到集合中,最后遍历集合取出数据,代码如下:

    class TaskWithResult implements Callable<String> {  
        private int id;  
      
        public TaskWithResult(int id) {  
            this.id = id;  
        }  
      
        @Override  
        public String call() throws Exception {  
            return "result of TaskWithResult " + id;  
        }  
    }  
      
    public class CallableTest {  
        public static void main(String[] args) throws InterruptedException,  
                ExecutionException {  
            ExecutorService exec = Executors.newCachedThreadPool();  
            ArrayList<Future<String>> results = new ArrayList<Future<String>>();    //Future 相当于是用来存放Executor执行的结果的一种容器  
            for (int i = 0; i < 10; i++) {  
                results.add(exec.submit(new TaskWithResult(i)));  
            }  
            for (Future<String> fs : results) {  
                if (fs.isDone()) {  
                    System.out.println(fs.get());  
                } else {  
                    System.out.println("Future result is not yet complete");  
                }  
            }  
            exec.shutdown();  
        }  
    }  

    注意ExecutorService 在Callable中使用的是submit(), 在Runnable中使用的是 execute()。

  • 相关阅读:
    《程序猿闭门造车》之NBPM工作流引擎
    CryptographicException异常处理方法
    nodejs简单模仿web.net web api
    Windows Mobile设备操作演示准备工作小记
    PPT定时器小记
    winDBG排错小记
    Ubuntu 16.04应用布署小记
    Ubuntu 16.04环境布署小记
    Ubuntu 16.04系统布署小记
    Dokuwiki布署小记
  • 原文地址:https://www.cnblogs.com/sanhuan/p/4740318.html
Copyright © 2011-2022 走看看