前言:
前面介绍了并发、并行,进程和线程的却别,接下来我们来看一下我们在java开发中如何创建一个线程,创建线程的方式又有那些,相比较这些方式那个比较好用
一、 继承Thread类:
在java开发中,java为我们提供了Thread类,我们想要创建一个线程时,只要继承Thread类重写里面的run()方法就可以了,下面来看一下简单的实现:
public class ThreadDemo extends Thread { @Override public void run() { System.out.println("创建一个线程" + Thread.currentThread().getName()); } public static void main(String[] args) { Thread thread = new ThreadDemo(); thread.start(); } }
二、实现Runnable接口:
在java提供了Thread线程类的时候,还为开发者提供了其他创建线程的方式,其中之一就是Runnable接口,只要实现此接口重写run()方法,同样可以创建一个线程,来看一下具体的实现(在这里使用了jdk1.8的新特性lambda表达式的写法)
public class RunnableDemo { public static void main(String[] args) { Thread task1 = new Thread(new Runnable() { @Override public void run() { System.out.println("匿名内部类创建线程" + Thread.currentThread().getName()); } }); task1.start(); Runnable task2 = () -> System.out.println("lambda表达式创建线程" + Thread.currentThread().getName()); new Thread(task2).start(); } }
三、实现callable接口
在java中为我们提供的另一个创建线程的方法callable接口,callable接口的实现相比较前两种方式稍微复杂,此接口需要使用FutureTask类的帮助执行,下图则是FutureTask类的结构图,可以看出FutureTask还是实现了Runnable接口,只不过在实现Runnable接口的同时实现了了另一个Future的接口。
从上面我们知道了要想使用Callable接口创建线程需要使用到FutureTask类,那么我们来看看一下使用Callable接口实现一个线程的方式:
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableDemo implements Callable<String> { @Override public String call() throws Exception { System.out.println("实现callable接口创建线程" + Thread.currentThread().getName()); return Thread.currentThread().getName(); } public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask task1= new FutureTask(new CallableDemo()); new Thread(task1).start(); System.out.println(task1.get()); FutureTask task2 = new FutureTask(() -> { System.out.println("使用lambda表达式创建线程" + Thread.currentThread().getName()); return Thread.currentThread().getName(); }); new Thread(task2).start(); System.out.println(task2.get()); } }
从下面的代码实现我们可以看出,Callable的实现与Runnable有一些区别,在Runnable接口中我们需要重写run()方法,而Callable是callI()方法,同时call方法是有一个返回值的泛型,这就是Runnable和Callable最大的区别,Callable接口可以返回线程执行的结果,并且用FutureTask类提供的一些方法进行获取、判断线程的状态等。