Java创建线程的三种方式

  • 继承Thread类,并重写run方法
  • 通过Runnable接口创建线程类
  • 通过Callable和Future创建线程

1. 继承Thread类来实现

继承Thread并重写run方法,创建该子类的示例,即创建了一个线程对象,调用线程对象的start()方法来启动该线程
1
2
3
4
5
6
7
8
9
10
11
public class ThreadDemo extends Thread{
//重写run方法
public void run(){
System.out.println("线程执行");
}

public static void main(String[] args){
//创建该子类的实例,并启动该线程
new ThreadDemo().start();
}
}

2.实现Runnable接口来创建线程类

定义一个实现Runnable,并重写Run()方法。创建该实现类的实例,并以此实例作为Thread的target来创建Thread对象。该Thread对象才是真正的线程对象。使用start()方法来启动该线程
1
2
3
4
5
6
7
8
9
10
    public class threadDemo implements Runnable{
@Override
public void run() {
System.out.println("线程运行");
}

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

使用lambda表达式

1
2
3
4
5
6
7
8
public class threadDemo {

public static void main(String[] args){
new Thread(()->{
System.out.println("线程运行");
}).start();
}
}

3.通过Callable和Future创建线程

创建Callable接口的实现类,并实现call()方法,call()方法是线程执行体。创建该实现类的实例,使用FutureTask类包装Callable对象,该FutureTask对象封装了Callable对象call()方法的返回值。使用FutureTask作为Thread对象的target创建线程,使用start()方法启动,调用FutrueTask对象的get方法来获得子线程执行结束后的返回值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    
public class threadDemo implements Callable<Integer> {

@Override
public Integer call() throws Exception {
System.out.println("线程运行");
return 666;
}

public static void main(String[] args){
FutureTask futureTask=new FutureTask(new threadDemo());

new Thread(futureTask).start();
try {
System.out.println("子线程执行结束后返回了:"+futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}

几种创建线程的方法的优缺点比较

1.通过继承Thread类来创建

    优点:实现简单。
    缺点:使用了继承,java有单继承局限。不能在继承其它类了。

2.使用Runnable接口来创建

    优点:不影响继承其它的类。多个线程即Thread可以公用一个target对象。就可以用Runnable来表示资源。结构清晰,符合面向对象的思想
    缺点:创建过程较复杂。无法获得线程执行后的结果

3.使用Callable接口创建的对象

    优点:不影响继承其它类。可以获得线程运行结束后的返回值.多个线程即Thread可以公用一个target对象。call()方法可以抛出异常。
    缺点:编程复杂