【JAVA】多线程的方法解析: Thread,Runnable,Callable

对于Java多线程的使用,方法有几种

  1. 直接使用 Thread执行,
  2. 使用Runnable 配合 Thread 使用:
  3. FutureTask 配合 Thread 使用,即使使用Callable类型。

       

方法二中:Tread代表线程,而Runnable代表可执行的任务,就是线程要执行的代码

方法一和方法二的区别:

        方法一将任务和线程合并在了一起,而方法二是将线程和任务分开

        使用方法2,可以更加容易与线程池等高级API配合,让任务类脱离 Thread的继承体现,更加灵活

而方法三的最大区别就是可以返回参数

1. 线程的创建

// 继承Thread类
class Thread1 extends Thread{
    @Override
    public void run(){
        System.out.println("Thread");
    }
}

// 实现Rubbable接口
class Thread2 implements Runnable{

    @Override
    public void run() {
        System.out.println("Runnable");
    }
}

// 实现Callable接口
class Thread3 implements Callable<Object>{

    @Override
    public Object call() throws Exception {
        return null;
    }
}

2. 线程的启动

Thread的启动

        // Thread的启动
        new Thread1().start();

 Runnable的启动

// Runnable的启动
new Thread(new Thread2()).start();

 Callable的启动

FutureTask<Object> futureTask = new FutureTask(new Thread3());
new Thread(futureTask).start();
try {
        Object object = futureTask.get();
        System.out.println(object);
    } catch (InterruptedException | ExecutionException e) {
         e.printStackTrace();
    }

 上述方法启动后的输出结果如下

Thread
Runnable
Callable
null

 3.区别

上面一共使用了三种方法,分别是Thread,Runnable和Callable。三者之间的区别我们从源码来看

// Thread的源码开头
public
class Thread implements Runnable {
    ...
}


// Runnable的源码
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

由源码知道,Thread也是使用了Runnable接口的,两者之间的区别在于我们一个是通过继承去引用,一个是使用接口去引用。

从而两者体现出来的不同最主要在继承和接口的区别

1、实现接口可以理解为是java对单继承的补充;

2、当子类继承父类,就自动拥有父类的功能,方法;

3、如果子类需要扩展功能,可以通过实现接口的方式扩展

解决的问题不同:

继承的价值主要在于:解决代码的复用性和可维护性。
接口的价值主要在于:设计,设计好各种规范(方法),让其它类去实现这些方法;

接口比继承更加灵活:接口比继承更加灵活,继承是满足is - a的关系,而接口只需满足like - a的关系。

接口在一定程度上实现代码解耦[即:接口规范性+动态绑定]

 所以在使用方面

不建议使用 继承Thread类的方法,因为可以避免OOP单继承局限性

推荐使用实现Runnable接口,因为可以避免单继承局限性,灵活方便,方便同一个对象被多个线程使用。

// Callable的源码
@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

 Callable接口最主要与Runnable接口对比,(因为Thread也是使用Runnable接口的)

两者最大的区别在于Callable可以抛出异常,同时可以返回值。

在线程池的运行方面也是有所不同的。

Callable接口的启动

        ExecutorService ser = Executors.newFixedThreadPool(1);
        Future<Object> future = ser.submit(new Thread3());
        try {
            Object result = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        ser.shutdown();

Runnable接口的启动

        ExecutorService ser = Executors.newFixedThreadPool(1);
        ser.execute(new Thread2());
        ser.shutdown();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值