一搬情况下大家都知道在 java 中创建一个新线程的二种方式,但是对第三种方式基本不熟,
甚至一些工作好几年的老程序员也不知道。
// 继承 Thread 类
public class NewThread extends Thread{
public void run(){}
}
// 实现 Runnable 接口
public class NewThread2 implements Runnable{
public void run(){}
}
上面2中方法比较常见,也是大家常用的,比较熟悉不做多说。主要说说下面这种实现方式
// 实现 Callable 接口 并且实现里面的 call 函数,不是 run 函数
public class Test {
// Callable 接口带泛型,设置 call 函数的返回值类型
static class NewThread3 implements Callable<Long> {
// 和 Runnable 不同的地方是 拥有返回值,并且可以抛出异常。
public Long call() throws Exception{
return null;
}
}
public static void main(String [] arg){
// 这种方式 穿件的线程需要使用 FutureTask 类进行包装,才能使用 Thread.start() 启动
// 例如
NewThread3 t3 = new NewThread3();
FutureTask<Long> task = new FutureTask<Long>(t3);
new Thread(task).start();
// 然后通过 task.get() 函数能够获取线程执行的结果(返回值)
// 如果线程没有执行完,get() 函数会一直阻塞等到线程执行结束
Long val = task.get();
// 另外可以通过 task.isDone() 函数校验是否执行完 - 该函数不阻塞
if(task.isDone()){
Long val = task.get();
System.out.println(val);
}else{
System.out.println("未执行完");
}
// 配合线程池使用 返回 Future 可以通过 Future 获取执行结果
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Long> val2 = executor.submit(t3);
System.out.println(val2.get());
// 或者 都可以
Future<Long> val3 = executor.submit(task);
System.out.println(val3.get());
}
}
如果在面试的时候遇到这个问题一定要说 三种,因为面试官其实就是想知道你知不知道第三种创建线程的方式。并且是否知道它有什么用。如果你只回答了 2 种,虽然没有错误,单这不是面试官想要的答案,会扣分的。
更多面试题请参考