1、Runnable和Callable的区别

(1) Callable规定的方法是 call(), Runnable规定的方法是 run()。

(2) Callable的任务执行后可返回值,而 Runnable的任务是不能返回值。

(3) call方法可以抛出异常, run方法不可以。

(4)运行 Callable任务可以拿到一个 Future对象

  Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get方法来获取结果,如果线程没有执行完, Future.get()方法可能会阻塞当前线程的执行;如果线程出现异常, Future.get()会 throws InterruptedException或者 ExecutionException;如果线程已经取消,会跑出 CancellationException。取消由 cancel方法来执行。
  isDone确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future但又不提供可用的结果,则可以声明 Future <?> 形式类型、并返回null作为底层任务的结果。

Future接口的定义如下:

  Future模式在请求发生时,会先产生一个 Future凭证给发出请求的客户,它的作用就像是 Proxy物件,同时,由一个新的执行线程持续进行目标物件的生成( Thread - Per - Message),真正的目标物件生成之后,将之设定至 Future之中,而当客户端真正需要目标物件时,目标物件也已经准备好,可以让客户提取使用。

结合 JDK的 Future来看,就是你 run线程后,你可以把线程的返回值赋给 Future并返回一个 Future对象。这时你可以立即拿到这个对象,然后进行下面的逻辑。但是如果你要 get这个 Future中的线程结果,就会被阻塞直到线程结束。

  相当于现在的期房,你把手续和钱都交上去了,就可以马上拿到合同,但只有合同没有房子。这个时候你已经是有房一族了,你可以先去买家电买装修(走下面的其他逻辑)。但是你要把家电和装修放进去,就必须等到房子完工(阻塞)。

2、Callable实现:

  submit方法会产生Future对象,它用Callable返回结果的特定类型进行了参数化,可以用isDone()的方法来查询Future是否已经完成。当任务完成是,它具有一个结果,可以调用get()方法来获取该结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package zeze;
  
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
  
/***
 *
 * @ClassName: EbayMultiplyThreadCheck
 * @Description: TODO
 * @author zeze
 * @date 2017年2月16日 上午8:49:46
 *
 */
public class EbayMultiplyThreadCheck {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newFixedThreadPool(10);
        ArrayList<Future<String>> results = new ArrayList<Future<String>>();
  
        for (int i = 0; i < 10; i++) {
            String email = "asd" + i + "@qq.com";
            results.add(exec.submit(new TaskWithResult(email)));
        }
  
        boolean isDone = false;
        while (!isDone) {
            isDone = true;
            for (Future<String> future : results) {
                if (!future.isDone()) {
                    isDone = false;
                    try {
                        Thread.sleep(1000);
                    catch (InterruptedException e) {
                    }
                    break;
                }
            }
        }
        exec.shutdown();
    }
}
  
class TaskWithResult implements Callable<String> {
  
    private String email;
  
    public TaskWithResult(String email) {
        this.email = email;
    }
  
    @Override
    public String call() {
        System.out.println(email);
        return null;
    }
  
}

3、Runnable 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/** 
* @Title: RunnableDemo.java
* @Package zeze
* @Description: TODO(用一句话描述该文件做什么)
* @author A18ccms A18ccms_gmail_com 
* @date 2017年3月13日 下午4:08:09
* @version V1.0 
*/
package zeze;
  
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
  
import javafx.animation.Animation.Status;
  
/**
 * @ClassName: RunnableDemo
 * @Description: TODO
 * @author zeze
 * @date 2017年3月13日 下午4:08:09
 *
 */
public class RunnableDemo implements Runnable {
  
    protected int countDown = 10;
    private static int taskCount = 0;
    private final int id = taskCount++;
  
    public RunnableDemo() {
    }
  
    public RunnableDemo(int countDown) {
        this.countDown = countDown;
    }
  
    public String status() {
        return "#" + id + "(" + (countDown > 0 ? countDown : "LiftOff!") + ").";
    }
  
    @Override
    public void run() {
        while (countDown-- > 0) {
            System.out.print(status());
            Thread.yield();// 将CPU从一个线程转移给另一个线程
        }
    }
  
    public static void main(String[] args) {
  
        System.out.println("这个任务的run()不是单独的线程驱动,是在main()中直接调用");
        RunnableDemo launch = new RunnableDemo();
        launch.run();
        System.out.println();
        System.out.println("************************************");
  
        System.out.println("在新线程中启动任务");
        Thread thread = new Thread(new RunnableDemo());
        thread.start();
        System.out.println("Waiting for LiftOff");
        System.out.println("************************************");
  
        System.out.println("添加多个线程去驱动更多的任务");
        for (int i = 0; i < 5; i++) {
            new Thread(new RunnableDemo()).start();
        }
        System.out.println("Waiting for LiftOff");
  
        System.out.println("************************************");
        System.out.println("使用executor");
        ExecutorService exec = Executors.newCachedThreadPool();
        exec=Executors.newFixedThreadPool(5);
        for (int i = 0; i < 5; i++) {
            exec.execute(new RunnableDemo());
        }
        exec.shutdown();
    }
  
}

Callable,Runnable异同的更多相关文章

  1. Callable, Runnable, Future, FutureTask

    Java并发编程之Callable, Runnable, Future, FutureTask Java中存在Callable, Runnable, Future, FutureTask这几个与线程相 ...

  2. Callable,Runnable比较及用法

    http://blog.csdn.net/xtwolf008/article/details/7713580 http://www.cnblogs.com/whgw/archive/2011/09/2 ...

  3. Callable,Runnable的区别及用法

    编写多线程程序一般有三种方法,Thread,Runnable,Callable. Runnable和Callable的区别是: (1)Callable规定的方法是call(),Runnable规定的方 ...

  4. java 创建线程的三种方法Callable,Runnable,Thread比较及用法

    转自:http://www.chinaitlab.com/Java/line/942440.html 编写多线程程序是为了实现多任务的并发执行,从而能够更好地与用户交互.一般有三种方法,Thread, ...

  5. 【Java】Callable,Runnable比较及用法

    1.Runnable和Callable的区别 (1) Callable规定的方法是 call(), Runnable规定的方法是 run(). (2) Callable的任务执行后可返回值,而 Run ...

  6. java并发编程--Runnable Callable及Future

    1.Runnable Runnable是个接口,使用很简单: 1. 实现该接口并重写run方法 2. 利用该类的对象创建线程 3. 线程启动时就会自动调用该对象的run方法 通常在开发中结合Execu ...

  7. 深入Callable及Runnable两个接口 获取线程返回结果

    今天碰到一个需要获取线程返回结果的业务场景,所以了解到了Callable接口. 先来看下下面这个例子: public class ThreadTest { public static void mai ...

  8. Java多线程Runnable与Callable区别与拓展

    我们先来分别看一下这两个接口 Runnable: // // Source code recreated from a .class file by IntelliJ IDEA // (powered ...

  9. Runnable与Callable区别

    相同点: 两者都是接口:(废话) 两者都可用来编写多线程程序: 两者都需要调用Thread.start()启动线程: 不同点: 两者最大的不同点是:实现Callable接口的任务线程能返回执行结果:而 ...

随机推荐

  1. 被误解的MVC和被神化的MVVM

    MVC 的历史 MVC,全称是 Model View Controller,是模型 (model)-视图 (view)-控制器 (controller) 的缩写.它表示的是一种常见的客户端软件开发框架 ...

  2. 【z09】关押罪犯

    描述 S城现有两座监狱,一共关押着N名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"(一个正整 ...

  3. jQuery异步提交form表单

    使用jquery.form.js官网现在地址表单插件来实现异步form表单提交. 先看看官方的介绍: /* Usage Note: ----------- Do not use both ajaxSu ...

  4. [Ramda] Declaratively Map Predicates to Object Properties Using Ramda where

    Sometimes you need to filter an array of objects or perform other conditional logic based on a combi ...

  5. 几款用jQuery写的h5小游戏

    人人都说前端用来做游戏是一件很困难的事情,遇到这些js的逻辑性问题,是不是有点懵?其实,做完一款游戏之后就会发现,没啥难的地方,差不多都是换汤不换药,作为爱玩游戏的我,也总结收集了几款比较流行的小软件 ...

  6. HTML/CSS 选择符优先级

    CSS的选择符优先级 1.同级样式默认后者覆盖前者 2.样式优先级 类型(1) < class[type](10)=伪类(10) < id(100) < style行间样式(1000 ...

  7. php二维数组中的查找(善于利用基础函数)

    php二维数组中的查找(善于利用基础函数) 一.总结 真没必要完整的写函数,善于借用 1.array_search()是在以为数组中来找,现在我们要在二维数组数组中来,肯定要借用这个 2.!==fal ...

  8. 【奇葩笔试】—— printf() 作为函数的参数及其返回值

    int f(int a, int b, int c){ return 0; } int main(int, char**){ f(printf("a"), printf(" ...

  9. 关于JavaScript对象概念的总结

    原文 https://www.jianshu.com/p/88213b499c4b 大纲 前言 1.对象的相关概念 2.对象的创建(简单创建) 3.对象的属性 3.1.数据属性 3.2.访问器属性 4 ...

  10. (一一六)新浪微博client的离线缓存实现思路

    上一节(一一五)利用NSKeyedArchiver实现随意对象转为二进制介绍了将随意对象转化为二进制数据和还原的方法.可用于实现本节介绍的微博数据离线缓存. 通过新浪官方的API能够发现,返回的微博数 ...