线程的创建与运行
1 继承Thread类
public class CreateThread01 {
// 继承Thread类
static class Thread01 extends Thread {
@Override
public void run() {
System.out.println(this.getName() + " 运行了");
}
}
public static void main(String[] args) {
new Thread01().start();
System.out.println("main over");
}
}
2 实现Runnable接口
public class CreateThread02 {
//实现Runnable接口
static class Thread02 implements Runnable {
@Override
public void run() {
System.out.println("hello world");
}
}
public static void main(String[] args) {
new Thread(new Thread02()).start();
System.out.println("main over");
}
}
注意Runnable接口中只有一个run方法,在java中这种接口称为函数式接口,故可以通过lambda表达式进行简化创建实现了Runnable接口的实例,具体方法如下
public static void main(String[] args) {
new Thread(() -> {
System.out.println("hello world");
}).start();
}
3 实现Callable接口
可以看到无论是通过继承Thread类还是通过实现Runnable接口,两者都是没有返回值的,可以通过FutureTask类来实现返回值的应用
package com.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class FutureTask_ {
public static void main(String[] args) {
// FutureTask<String> task = new FutureTask<>(new Callable<String>() {
// @Override
// public String call() throws Exception {
// return "hello world";
// }
// });
//此处采用了lambda表达式,因为Callable是一个函数式泛型接口,内部只有一个call()方法
FutureTask<String> task = new FutureTask<>(() -> "hello world");
new Thread(task).start();
try {
String s = task.get();
System.out.println(s);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
4 三种方式的区别
1 Thread方式:能够在run方法中直接通过this关键字来调用该线程自己;每次执行不同的任务就需要在写一份相同的任务代码,即任务与代码之间没有分离;
2 Runnable方式:实现了该接口的类仍然可以继承其他的类,规避了Thread方式中类不能再继承其他类的缺点,但是要想获得线程本身需要通过Thread.currentThread()方式;
3 FutureTask方式:可以对线程的返回值进行再利用