talk is cheap ,show me your code
通过Thread的方式进行创建
public class CatThread extends Thread {
@Override
public void run() {
System.out.println("喵");
}
}
通过Runable的方式进行创建
public class DogThread implements Runnable{
@Override
public void run() {
System.out.println("汪");
}
}
通过Callable的方式进行创建
import java.util.concurrent.Callable;
public class WolfThread implements Callable<String> {
@Override
public String call() throws Exception {
return "嗷";
}
}
Main方法
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// write your code here
//runnable只是一个接口,要想运行run方法需要先赋值给Thread
DogThread dog = new DogThread();
Thread dogThread = new Thread(dog);
//直接创建
CatThread catThread = new CatThread();
//callable接口可以返回值,但是需要先给futureTask然后再给Thread,通过FutureTask的get方法可以获取返回值
WolfThread wolf = new WolfThread();
FutureTask<String> ft = new FutureTask<>(wolf);
Thread wolfThread = new Thread(ft);
dogThread.start();
catThread.start();
wolfThread.start();
System.out.println(ft.get());
}
}
直接运行的结果:
总结一下的话就是thread编写方便,但是因为是继承的关系扩展麻烦,而Runable是接口扩展方便,就是编写麻烦点,而callable的话有返回值。其实一般来说使用哪一种方式都是看需求而已,但是一般来说我比较习惯使用Runable
这里顺便探讨一下,为什么实现Runable需要把Runable放入Thread的构造函数
这个是Thread类的源码,可以看到主要实现是init方法,在init方法中,通过参数把runable传入给Thread
这里顺便看一下target还有哪里被调用
可以看到,使用run方法的时候判断runable是否为空,不为空的话就运行runable的run方法