Runnable和Callable的使用

在 Java 中,创建并启动一个新的线程通常有两种主要的方式:继承 Thread 类和实现 Runnable 接口。

  1. 通过继承 Thread 类来创建一个新的线程类,并重写 Thread 类的 run() 方法。
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread is running");
    }

    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start();  //启动线程
    }
}
  1. 通过实现 Runnable 接口并实现其 run() 方法,然后将 Runnable 实例传递给 Thread 对象。
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Thread is running");
    }

    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start();
    }
}
特性继承 Thread实现 Runnable 接口
继承不支持多继承,限制较大支持多继承,更灵活
代码解耦线程逻辑和线程控制耦合线程逻辑和线程控制分离
复用性不易复用易复用
共享资源需要额外处理自然适应共享资源

ps:若两个同时使用呢?

class BothRunnableThread {
    public static void main(String[] args) {
        // 创建一个匿名内部类实现 Runnable 接口的 run 方法
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 这个 run 方法来自于 Runnable 接口
                System.out.println("I am runnable");
            }
        }) {
            // 创建一个匿名内部类继承 Thread 类并重写其 run 方法
            @Override
            public void run() {
                // 这个 run 方法来自于 Thread 类
                System.out.println("I am thread");
            }
        }.start();  // 启动线程
    }
}

结果是:
在这里插入图片描述

原因:
创建了一个实现了 Runnable 接口的匿名内部类的对象,然后这个Runnable类的匿名内部类的对象被传给Thread的target。
在这里插入图片描述

在这里插入图片描述
但是Thread的下面三行run方法被重写了,也就不用管Runnable类的target了,虽然Runnable类的target的run方法被重写了,所以没机会执行Runnable类的target的run方法了。
在这里插入图片描述
所以本质上创建新线程都是通过new Thread()创建新线程对象,然后使用它的start()方法启动线程,第一种继承Thread然后重写Thread的run()方法也不例外,因为只是重写run()方法而已。


至于基于callable接口的方式,最终是要把实现了callable接口的实例对象通过FutureTask(实现了Future和Runnable接口)包装成Runnable任务,再交给Thread去执行,所以这个其实可以和实习Runnable接口看成同一类。


实例代码:

package study;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class day03_runnable和callable {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Task1 task1 = new Task1();
        new Thread(task1).start();

        Task2 task2 = new Task2(10);
        FutureTask<Long> futureTask = new FutureTask<Long>(task2);
        new Thread(futureTask).start();  // FutureTask实现了Runnable, 所以可以传入Thread的构造函数

        Long result = futureTask.get(); // 死等计算完成结果
        System.out.println(result);
    }
}

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

class Task2 implements Callable<Long> {
    private long num;

    public Task2(int num) {
        this.num = num;
    }

    @Override
    public Long call() throws Exception {
        return this.num + 10;
    }
}


  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重剑DS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值