一:提要
在学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() 创建,其他的方法只是在此基础上演变的。
若是对读者有所帮助,大家可以点赞+留言+收藏,我们也可以一起讨论有关编程的知识哦!