Callable接口:

1
2
3
public interface Callable<V> {
    V call() throws Exception;
}

Runnable接口:

1
2
3
public interface Runnable {
    public abstract void run();
}

相同点

  1. 两者都是接口;(废话)
  2. 两者都可用来编写多线程程序;
  3. 两者都需要调用Thread.start()启动线程;

不同点

  1. 两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
  2. Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

注意点

  • Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞!

Callable工作的Demo:

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
package com.callable.runnable;
 
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
 
/**
 * Created on Jason 2018/10/12.
 */
public class CallableImpl implements Callable<String> {
 
    public CallableImpl(String acceptStr) {
        this.acceptStr = acceptStr;
    }
 
    private String acceptStr;
 
    @Override
    public String call() throws Exception {
        // 任务阻塞 1 秒
        Thread.sleep(1000);
        return this.acceptStr + " append some chars and return it!";
    }
 
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<String> callable = new CallableImpl("my callable test!");
        FutureTask<String> task = new FutureTask<>(callable);
        long beginTime = System.currentTimeMillis();
        // 创建线程
        new Thread(task).start();
        // 调用get()阻塞主线程,反之,线程不会阻塞
        String result = task.get();
        long endTime = System.currentTimeMillis();
        System.out.println("hello : " + result);
        System.out.println("cast : " + (endTime - beginTime) / 1000 " second!");
    }
}

测试结果:

1
2
3
4
hello : my callable test! append some chars and return it!
cast : 1 second!
 
Process finished with exit code 0

Runnable工作的Demo:

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
package com.callable.runnable;
 
/**
 * Created on Jason 2018/10/12.
 */
public class RunnableImpl implements Runnable {
 
    public RunnableImpl(String acceptStr) {
        this.acceptStr = acceptStr;
    }
 
    private String acceptStr;
 
    @Override
    public void run() {
        try {
            // 线程阻塞 1 秒,此时有异常产生,只能在方法内部消化,无法上抛
            Thread.sleep(1000);
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 最终处理结果无法返回
        System.out.println("hello : " this.acceptStr);
    }
 
    public static void main(String[] args) {
        Runnable runnable = new RunnableImpl("my runable test!");
        long beginTime = System.currentTimeMillis();
        new Thread(runnable).start();
        long endTime = System.currentTimeMillis();
        System.out.println("cast : " + (endTime - beginTime) / 1000 " second!");
    }
}

测试结果:

1
2
3
4
cast : 0 second!
hello : my runable test!
 
Process finished with exit code 0

比较了两者后,发现Callable在很多特殊的场景下还是很有用的!最后留点代码,加深对Callable的认识!

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
package com.inte.fork;
 
/**
 * Created on Jason 2018/10/12.
 */
 
import java.util.*;
import java.util.concurrent.*;
 
import static java.util.Arrays.asList;
 
public class Sums {
 
    static class Sum implements Callable<Long> {
        private final long from;
        private final long to;
 
        Sum(long from, long to) {
            this.from = from;
            this.to = to;
        }
 
        @Override
        public Long call() {
            long acc = 0;
            for (long i = from; i <= to; i++) {
                acc = acc + i;
            }
            System.out.println(Thread.currentThread().getName() + " : " + acc);
            return acc;
        }
    }
 
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        List<Future<Long>> results = executor.invokeAll(asList(
                new Sum(010), new Sum(0, 1_000), new Sum(0, 1_000_000)
        ));
        executor.shutdown();
 
        for (Future<Long> result : results) {
            System.out.println(result.get());
        }
    }
}

callbale 和runnable 区别的更多相关文章

  1. java多线程机制中的Thread和Runnable()区别

    1.java语言使用Thread类及其子类对象来表示线程,新建的一个线程声明周期中经历 新建.(声明一个线程,此时他已经有了相应的内存空间和其他资源),运行(线程创建之久就据用了运行的条件,一旦轮到使 ...

  2. Thread Runnable 区别

    [线程的并发与并行] 在单CPU系统中,系统调度在某一时刻只能让一个线程运行,虽然这种调试机制有多种形式(大多数是时间片轮巡为主),但无论如何,要通过不断切换需要运行的线程让其运行的方式就叫并发(co ...

  3. java Thread和Runnable区别

    ①Thread类实现了Runnable接口,主要构造方法为Thread(Runnable target).Thread(Runnable target,String name).Thread(Stri ...

  4. jdk1.8源码Thread与Runnable区别

    一.概念 Thread实现了Runnable接口 public class Thread implements Runnable { /* Make sure registerNatives is t ...

  5. Java 使用线程方式Thread和Runnable,以及Thread与Runnable的区别

    一. java中实现线程的方式有Thread和Runnable Thread: public class Thread1 extends Thread{ @Override public void r ...

  6. Thread 和 Runnable

    Thread 和 Runnable 1. 简介 Java 主要是通过 java.lang.Thread 类以及 java.lang.Runnable 接口实现线程机制的. Thread 类为底层操作系 ...

  7. java线程生命周期及其对应方法

    http://blog.sina.com.cn/s/blog_a8aa82cc0101ktrm.html http://wenku.baidu.com/view/c242df69011ca300a6c ...

  8. 最近面了不少java开发,据此来说下我的感受:哪怕事先只准备1小时,成功概率也能大大提升

    本人最近几年一直在做java后端方面的技术面试官,而在最近两周,又密集了面试了一些java初级和高级开发的候选人,在面试过程中,我自认为比较慎重,遇到问题回答不好的候选人,我总会再三从不同方面提问,只 ...

  9. Java中的I/O 线程 网络

    Java学习总结--I/O,线程,网络题目整理 I/O 1.有什么理由必须要用字符流? 答:处理字符数据的语法更方便.自动化字符编码 2.插入哪些代码可以让下面的代码正确编译? Console con ...

随机推荐

  1. 【性能测试实战:jmeter+k8s+微服务+skywalking+efk】系列之:性能测试场景设计

    说明: 本文是基于虚拟机环境配置设计的 性能测试需求 总tps≥100 每个业务的rt<500ms 持续稳定跑50万业务量 单场景 目的:找到单场景的性能问题,为容量场景提供参考,如果低于容量场 ...

  2. Windows系统散列值获取分析与防范

    LM Hash && NTLM Hash Windows操作系统通常使用两种方法对用户的明文进行加密处理,在域环境中,用户信息存储在ntds.dit中,加密后为散列值.Windows操 ...

  3. Oracle之SQL限定查询

    WHERE限定条件 /*语法结构:SELECT * | 列名1[,列名2...] | 表达式FROM 表名 WHERE 限定条件; */ --查询职位为CLERK的员工信息 SELECT * FROM ...

  4. wurstmeister/kafka:docker构建kafka遇到的问题

    1. kafka 容器无法启动 过程描述: docker ps -a 看到 Exited docker logs a87d9cd2a8ac 查看日志: 发现是内存不够 解决方案: 修改 kafka的J ...

  5. TCP三次握手中SYN,ACK,seq ack的含义

    转至:https://www.cnblogs.com/muyi23333/articles/13841268.html 1.TCP 为什么三次握手而不是两次握手 1.防止已失效的连接请求又传送到服务器 ...

  6. 我对maptask 和 reducetask的理解

    MapTask: 首先经过 FileInputFormat 判断该文件是否要进行切片,如果是我们自定义的FileInputFormat基本上重写isSplit方法返回为false表示不进行切片,那么就 ...

  7. docker学习笔记(5)——docker场景问题汇总(docker权限问题、docker文件目录、查看docker历史日志文件)

    参考资料: 1.博客1:https://www.jianshu.com/p/d645e2ed4bb1 使用docker的时候有一些常见问题: docker权限问题:一般输入docker命令前面都要加s ...

  8. pyqt(四)

    八.布局 1. 布局简介 一个pyqt窗口中可以有多个控件 所谓布局,指的就是多个控件在窗口中的展示方式 布局方式大致分为: 水平布局 竖直布局 网格布局 表单布局 2. 水平布局QHBoxLayou ...

  9. python的变量与基本数据类型

    今日内容 python多版本共存 python的注释 python的变量与常量 变量的本质 变量的命名规范 python基本数据类型 内容详细 python多版本共存 先将两个版本的python解释器 ...

  10. source tree的使用

    参看博客: https://blog.csdn.net/syq8023/article/details/89844030 http://jingyan.baidu.com/album/59703552 ...