创建线程的四种方式

我们创建线程池一般有四种方式,分别是:
1.继承Thread类,重写run()方法;
2.实现Runnable接口,重写run()方法;
3.实现Callable接口,重写call()方法;
4.使用线程池创建线程;
本文就介绍下前3种创建线程的方式,第4种使用线程池的方式,大家可以查看下Java之线程池入门

一、继承Thread类

步骤:
1.创建一个类继承Thread类,重写其run()方法,在run()方法中编写需要执行的任务;
2.创建继续Thread类的对象;
3.调用其对象的start()方法,该方法表示启动一个线程,线程处于就绪状态,如果获取到cpu执行权,则会调用run()方法,执行对应的任务;
注意:如果调用run()方法,就是普通的方法调用;
Demo1:

public class ThreadDemo {
   
    public static void main(String[] args) {
        MyThread myThread = new  MyThread();
        myThread.start();
    }
}

class MyThread extends Thread{

    @Override
    public void run() {
        System.out.println("继承thread类实现线程---");
    }
}

运行结果:

继承thread类实现线程---

二、实现Runnable接口

步骤:
1.创建一个类,实现Runnable接口,重写run()方法,编写需要执行的代码;
2.创建一个Runnable接口实现类的对象;
3.将此对象作为形参传递到Thread类的构造器中,创建Thread类的对象,调用start()方法,启动线程;
Demo2:

public class ThreadDemo {

    public static void main(String[] args) {
        MyThread myThread = new  MyThread();
        new Thread(myThread).start();
    }
}

class MyThread implements Runnable{

    @Override
    public void run() {
        System.out.println("实现Runnable接口来创建线程---");
    }
}

运行结果:

实现Runnable接口来创建线程---

继承方式和这种实现接口的方式的联系和区别:
1.联系:public class Thread implements Runnable, 继承Thread 方式中Thread也实现了Runnable接口
在这里插入图片描述
2.实现接口的方式要优先继承方式:

  1. 避免了java只能单个继承的局限性
  2. 如果多个线程要操作同一份资源或者数据,使用实现接口的方式更加合适。

三、实现Callable接口

步骤:
1.创建Callable接口的实现类,并实现call()方法,该方法具有返回值,并且可以抛异常;
2.创建Callable实现类的实例,并使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值;
3.使用FutureTask对象作为Thread对象的target创建并启动新线程;
4.调用FutureTask对象的get()方法来获取子线程执行结束后的返回值;
demo3:

public class ThreadDemo {

    public static void main(String[] args) {
        MyThread myThread = new  MyThread();
        FutureTask<Integer> futureTask = new FutureTask<>(myThread);
        new Thread(futureTask).start();
        try {
            Integer integer = futureTask.get();
            System.out.println("执行结果:"+integer);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class MyThread implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        System.out.println("实现Callable接口来创建线程---");
        Integer i = 6/2;
        return i;
    }
}

运行结果:

实现Callable接口来创建线程---
执行结果:3

实现Runnable和实现Callable接口的方式基本相同,
不过是后者执行call()方法有返回值,并且可以抛出异常,前者线程执行体run()方法无返回值.

Callable 和 Runnable接口的区别

  1. Callable规定的方法是call(),而Runnable规定的方法是run()。
  2. Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
  3. call()方法可抛出异常,而run()方法是不能抛出异常的。

我们看到Runnable和Callable传到Thread类的构造器中表面上方式是“不一样”的,我们看到Thread类的构造器:
在这里插入图片描述
我们上面使用的都是public Thread(Runnable target)构造器,实现Runnable方式直接将其实现类的对象传入即可;但是实现Callable接口,我们使用的FutureTask来保证实现Callable接口类的对象,在传入Thread构造器中,那FutureTask和Runnable有什么关系呢?

我们点到FutureTask类的源码中可以发现其实现了RunnableFuture接口
在这里插入图片描述
然后继续点进RunnableFuture接口的源码中,我们发现其继承了Runnable接口。
在这里插入图片描述
看到这里不知道大家发现没有,上面三种方式都和Runnable接口有联系;Thread类是实现Runnable,Callable封装成FutureTask,FutureTask实现RunnableFuture,RunnableFuture继承Runnable,所以Callable也算是一种Runnable,所以三种实现方式本质上都是Runnable实现。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值