2.创建线程的三种方式


导言 

创建线程主要是有三种方式,第一种继承thread的类,第二种实现runnable接口。第三种实现callable接口

 

继承thread

定义 MyThread

首先我们来看第一种,继承thread,我们先自定义一个类,然后使他去继承thread类,继承完以后,我们需要去重写它里面的run方法,线程启动以后,它就会自动去调用这个 run方法。所以我们也要把自己的任务写在run方法里面,

package com.chenjie.executor.day02;

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println("将要执行的内容写在run方法里面");
    }
}

使用

下面我们来看看如何使用这个自定义线程。第一步,我们还要创建mythread的对象,第二步我们要调用它的start方法来启动这个线程,我们看一下执行结果是怎样的。

package com.chenjie.executor.day02;

public class Main1 {

    public static void main(String[] args) {
        //创建线程
        MyThread myThread=new MyThread();
        //启动线程
        myThread.start();
    }
}

结果

将要执行的内容写在run方法里面

Process finished with exit code 0

从执行结果来看,输出的内容和我们在run方法里面写的是一样的,第一种创业线程的方式呢我们就介绍完了。

实现runnable接口

我们再来看第二种创建线程的方式。第二种创建线程的方式呢是实现runnable接口

定义 task

我们还是先自定义一个类,然后呢让这个类去实现runnable不接口。它里面有个run方法,其实啊它也是实现了这个 runnable接口的。这里呢我们还需要注意一点,就是runnable它仅仅只是一个接口,它没有启动线程的能力搭配着thread的来使用。 

package com.chenjie.executor.day02;

/**
 * 自定义task
 */
public class Task  implements Runnable{
    @Override
    public void run() {
        System.out.println("将要执行的内容写在run方法中");
    }
}

使用

 

下面呢我们来看一下这个 runnable是如何搭配thread的来使用的。第一步,我们要创建task对象,第二步的我们要创建thread对象。我们在创建thread对象的时候,我们需要将task作为参数传递给他。第三步就是调用线程的start的方法来启动现场。

package com.chenjie.executor.day02;

public class Main2 {
    public static void main(String[] args) {
        //创建自定义task
        Task task=new Task();
        //创建线程,把task放进去
        Thread thread = new Thread(task);
        //启动线程
        thread.start();
    }
}

结果

我们来看一下执行结果是怎么样的。从运行结果来看,输出的内容和我们之前写的方案里面的内容是一样的,第二种创建线程的方式呢介绍完毕。

将要执行的内容写在run方法中

Process finished with exit code 0

实现callable

最后我们来看一下第三种创建线程的方式。第三种创业线程的方式呢是实现callable,我们还是先自定义一个类,然后呢去实现这个callable接口,和runnable还是有点不一样的。 

自定义callable

runnable接口呢它只是仅仅只是执行任务,它里面没有说要返回任务的执行结果,但callable接口不同的是,他执行完任务以后,他需要返回一个执行结果,所以呢我们需要在callable接口后面指定一下这个返回结构的类型,也就是callable接口它是带泛型的,指定一个泛型,这里假设我们返回的结果是一个字符串,所以我们在后面写上一个string类型,指定完类型以后,我们就需要重写callable里面的一个call方法,那么这个 call方法和run方法的作用是一样的,只不过呢方法它里面多了一个范围值,因为他要返回任务执行的结果,那这个结果类型呢就是我们在上面刚刚指定的这个类型,这里需要说明一点,callable和runnable口他们都没用启动线程的能力,所以啊他们两人都要搭配线程来使用。

package com.chenjie.executor.day02;

import java.util.concurrent.Callable;

public class Result implements Callable<String> {
    @Override
    public String call()  {
        String reslut="将要执行的内容写在run方法中";
        return reslut;
    }
}

使用

下面我们来看一下如何使用callable。第一步我们还要创建 result对象,第二步呢我们要借助 futuretask来获取这个结果的。 

所以我们要创建一个futuretask对象,并且我们要将result这个对象传递给futuretask。第三步呢我们还是要创建一个线程,因为我们刚刚说了,无论是 callable还是runnable,他们都没有启动线程的能力,所以第三步还是要创建一个thread对象。同理,我们需要将futuretask的对象作为参数传递给 thread。thread现在启动以后呢去执行这个任务。再就是启动线程,到这里还没有完,这几步做完以后,我们仅仅只是将任务执行了,对吧?但是我们没有获取到任务返回的结果,那么获取任务返回的结果呢,就是通过futuretask的get方法,这里需要注意一点呢就是get方法它有一个异常要抛出来,这里我们就简单的给它捕获一下就可以了。 

 

package com.chenjie.executor.day02;

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

public class Main3 {
    public static void main(String[] args) {
        //创建自定义task
        Result result = new Result();
        //创建异步任务FutureTask
        FutureTask<String> futureTask=new FutureTask(result);
        //创建线程,把task放进去
        Thread thread = new Thread(futureTask);
        //启动线程
        thread.start();
        try {
            String value = futureTask.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

 

 

结果

最后我们就输出我们拿到的结果,运行程序我们来看一下结果是怎样的。

将要执行的内容写在run方法中

Process finished with exit code 0

从运行结果来看,是吧?和我们在callable里面返回的结果是一致的。

至此呢我们创建线程的三种方式都介绍完毕了。

总结

那么再来总结一下今天的内容,今天我们主要讲了创建现成的三种方式

分别是继承thread的类,

实现runnable接口

实现callable接口

后面两者他们都没有启动线程的能力,所以他们都需要借助thread的来执行任务。这三种方式啊他们使用场景不相同的。 

 

你比如说所谓的这种thread,它只是用单继承的情况,为什么?因为Java它只支持单继承,不支持多继承。所以你继承了所谓的类,就不能再继承其他类,这种方式的局限性太大了,所以不建议大家经常使用。至于后面两种方式是非常推荐大家在日常开发中使用的,runnable他就用到没有返回值的任务上面,而callable它就可以用在有返回值的任务上面。 

可以发现第一个直接创建线程就可以使用了,第二个是实现runable,他是一个没有返回值的task,而第三个实现callable,我们可以发现在main3方法中创建了futureTask对象,其实这个对象就相当于我们第二步创建的那个task,只是我们在第三种方法中创建了更加细粒度的callable


   

posted @ 2022-04-29 12:00  小陈子博客  阅读(428)  评论(0编辑  收藏  举报