创建线程的几种方式

一:提要

在学Java基础的时候,老师说创建线程一般就有四种方法,即继承Thread类,实现Runnable接口,实现Callable接口,使用线程池创建线程,这四种方法确实是很常见的创建线程的方法,可是我们还有没有其他得方法创建线程呢?于是在好奇心的驱动下,我查阅了一些关于Java的知识资料后发现,其实创建线程还有其他的几种方法,下面我将具体给大家讲解

二:创建线程的基本四种方法

1.继承Thread类,并重写run()方法;

2.实现Runnable接口,并传递给Thread构造器;

3.实现Callable接口,创建有返回值的线程;

4.使用线程池创建线程池;

三:具体实现 

1.继承Thread类

这是最基本的一个创建线程的方法,创建一个Thread_test类继承Thread类,并重写run()方法,我们通过代码来实现:

public class Thraed_test extends Thread{
    public static void main(String[] args) {
        new Thraed_test().start();//启动线程
    }

    //重写run方法
    @Override
    public void run(){
        System.out.println("我是通过继承Thread类的线程");
    }
}

对于上述的代码,如果采用匿名内部类的写法也是可以实现的,也可以简化代码。

public class Thread_test2 extends Thread{
    public static void main(String[] args) {
        new Thread("通过使用匿名内部类实现") {
            @Override
            public void run(){
                System.out.println(Thread.currentThread().getName());
            }
        }.start();
    }
}
//打印结果为:通过使用匿名内部类实现;

2.实现Runnable接口

这也是基本的写法之一,实现Runnable接口并重写run()方法,通过代码如下

public class Runnable_test implements Runnable{
    public static void main(String[] args) {
        Runnable_test rt = new Runnable_test();
        new Thread(rt).start();
    }

    //重写run方法
    @Override
    public void run() {
        System.out.println("我是通过实现Runnable接口实现的");
    }
}
//打印结果为:我是通过实现Runnable接口实现的;

3.实现Callable接口

这种方式是通过实现Callable接口实现可以有返回值的线程

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

public class Callable_test implements Callable<String> {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable_test ct = new Callable_test();
        FutureTask<String> ft = new FutureTask<>(ct);
        new Thread(ft).start();
        System.out.println(ft.get());
    }
    //重写call()方法
    @Override
    public String call() throws Exception {
        return "我是通过实现Callable接口实现";
    }
}
//打印结果:我是通过实现Callable接口实现。

注意:这里使用了FutureTask类,通过FutureTask 包装然后执行:(使用步骤:创建callable的实现类实体对象,然后通过FutureTask进行包装,再将包装后的FutureTask对象作为参数传给线程,调用start方法开启线程。获取步骤:通过调用FutureTask的get()方法进行获取返回结果。get()方法会阻塞当前线程,直到获取结果为止)

FutureTask常用于异步获取执行结果或取消执行任务的场景。


4.使用线程池 

在这里我们使用从jdk1.8开始引用的CompletableFuture类,使用这个的好处,引入了函数式编程,异步任务组合等强大的特性。

import java.util.concurrent.CompletableFuture;

public class Thread_pool {
    public static void main(String[] args) throws InterruptedException {
        CompletableFuture<String> ct = CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName()+"  "+"我是通过线程池创建的线程");
            return "我是通过线程池创建的线程";
        });
        //线程阻塞,以便更好地观看结果
        Thread.sleep(3000);
    }
}

 执行结果如下:


5.使用FutureTask类

在我学习的时候我看到用这个FutureTask类感觉好熟悉,这与在实现Callable接口中使用的FutureTask类是一样的。在这里我们采用lambda表达式来实现

import java.util.concurrent.FutureTask;

public class FutureTask_test {
    public static void main(String[] args) {
        FutureTask<String> ft = new FutureTask(()->{
            System.out.println(Thread.currentThread().getName()+"我是通过使用FutureTask类实现的");
            return "我是通过使用FutureTask类实现的";
        });
        new Thread(ft).start();
    }
}

执行结果如下: 


6.使用Timer定时器类

在查阅Java相关资料时得知,在jdk1.3时就引入了Timer定时器类,用来执行特定任务,在Timer类中,只需要传入两个数字,第一个启动数字代表启动开始多久后才开始执行,第二个为间隔数字代表每间隔多久执行一次,下面我们通过代码来实现

import java.util.Timer;
import java.util.TimerTask;

public class Timer_test {
    public static void main(String[] args) {
        Timer time = new Timer();
        time.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("我是通过定时器类实现的线程");
            }
        },1000);
    }
}

 执行结果如下:


7.使用ForkJoin线程池或使用Stream并行流

在浏览博客园时,我看到了一位网友提出的第7种方法是使用ForkJoin线程池,这是jdk1.7引入的新线程池,这种方法是基于分治思想的。而在jdk1.8中parallelStream并行流,默认就是使用ForkJoin实现的。

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ForkJoinPool;

public class ForkJoin_test {
    public static void main(String[] args) {
        ForkJoinPool fj = new ForkJoinPool();
        fj.execute(()->{
            System.out.println(Thread.currentThread().getName()+"我是通过ForkJoin线程池创建的线程");
        });
        //parallelStream流
        List<String> list = Arrays.asList(Thread.currentThread().getName()+"  "+"parallelStream流");
        list.parallelStream().forEach(System.out::println);
    }
}

执行结果如下:


四:总结

其实,我们在学习的过程中要掌握前四种创建线程的方法就可以了,后续创建线程的方法,了解即可。

在这么多的创建的线程的方法中,我认为真正的创建线程的方法是通过 new Thread().start() 创建,其他的方法只是在此基础上演变的。

若是对读者有所帮助,大家可以点赞+留言+收藏,我们也可以一起讨论有关编程的知识哦!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值