Runnable和Callable区别[通俗易懂]

RunnableRunnable是一个接口,该接口中只有一个run方法,实现Runnable接口的类需要重写run方法,然后可以把这个类作为Thread类的一个参数,来创建线程,具体的用法有两种:创建一个类,实现Runnable接口,重写run方法classMyThreadimplementsRunnable{@Overridepublicvoidrun(){System.out.println(“MyThread”);}}使

大家好,又见面了,我是你们的朋友全栈君。

Runnable

Runnable是一个接口,该接口中只有一个run方法,实现Runnable接口的类需要重写run方法,然后可以把这个类作为Thread类的一个参数,来创建线程,具体的用法有两种:

  • 创建一个类,实现Runnable接口,重写run方法
class MyThread implements Runnable { 
   
    @Override
    public void run() { 
   
        System.out.println("My Thread");
    }
}
  • 使用匿名内部类创建一个对象
class Test{ 
   
    public static void main(String[] args) { 
   
        Runnable myThread = new Runnable() { 
   
            @Override
            public void run() { 
   
                System.out.println("My Thread");
            }
        };
    }
}    

Callable

Calllable同样也是一个接口,也是用来创建线程的,只不过略微有点区别,Callable中的是call方法,同样可以由一个类实现Callable接口,重写call方法,然后作为Thread的参数,只不过用法不同,call方法是带有返回值的,而且它创建出来的对象也不能直接作为Thread的参数,而是需要用FurtherTask类包裹起来,然后再传进去,call方法的返回值需要用的FurtherTask中的get方法来获取。用法如下:

class MyThread implements Callable<String> { 
   
    private int ticket = 10 ; // 一共10张票
    @Override
    public String call() throws Exception { 
   
        while(this.ticket>0){ 
   
            System.out.println("剩余票数:"+this.ticket -- );
        }
        return "票卖完了,下次吧。。。" ;
    }
}
public class Test{ 
   
    public static void main(String[] args) throws Exception { 
   
        FutureTask<String> task = new FutureTask<>(new MyThread()) ;
        new Thread(task).start();
        System.out.println(task.get());
    }
}    

两者的区别

相同点

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

不同点

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

特殊:使用FutureTask的get方法时会让主线程进入阻塞状态,因为它要确保call方法已经执行完毕,要结果出来之后才会唤醒主进程。不调用get方法就不会阻塞,也就说Callable如果不调用get方法,效果就和Runnable差不多。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/126152.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 【通信系统仿真设计】基于MATLAB的直接序列扩频通信系统仿真

    【通信系统仿真设计】基于MATLAB的直接序列扩频通信系统仿真直接扩频序列调制是用速率很高的伪噪声码序列与信息码序列模二相加(波形相乘)后得到复合码序列,用复合码序列去控制载波相位,从而获得直接扩频序列信号的。直接扩频通信具有低截获概率、抗干扰能力强以及易于实现码分多址等优点,在抗干扰通信及民用移动通信中都得到了广泛的应用。

    2022年6月3日
    48
  • An overview of the Web(Web概述)

    An overview of the Web(Web概述)

    2021年6月8日
    100
  • ORA-12514 解决方法

    ORA-12514 解决方法场景:修改oracle系统参数之后,数据库重启,客户端报ORA-12514错误,其实这只是表象,实际并非Listener的问题。SELECT*FROMV$RESOURCE_LIMIT根据

    2022年7月1日
    28
  • viewstub 的详细用法_pageinfo用法

    viewstub 的详细用法_pageinfo用法在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局。那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Infl…

    2022年4月19日
    50
  • C++对象数组「建议收藏」

    C++对象数组「建议收藏」C++对象数组一、对象数组1.C++对象数组的定义:类名数组名[元素个数]例:Studentstu[10];2.对象数组访问形式:数组名[下标].成员名;例:stu[i].print();3.对象数组的初始化:对象数组的初始化通常也是由构造函数来完成的例:关于对象数组的几点说明:  (1)在建立对象数组的时候需要调用构造函数。如果对象数组有100个元素,就需…

    2022年7月12日
    19
  • PriorityQueue(优先级队列总结)

    PriorityQueue(优先级队列总结)一,概念队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列 数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(PriorityQueue)二,PriorityQueue的特性Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlo.

    2022年5月1日
    52

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号