面试的过程中我们经常会遇到创建线程(对象)有多少种方式,具体如何实现等类似的问题,下面我们就来详细探讨下
首先明确创建线程主要有四种方式:
1、 通过实现Runnable接口来创建线程
2、 通过继承Thread类来创建线程
3、 通过实现Callable接口来创建线程
4、 通过(Executor框架)线程池创建线程
在你简述这四种方式创建线程的方式后,面试官可能还会问你Runnable接口和Callable接口的区别是?
1、 Callable规定方法是call(),Runnable规定的方法是run()。
2、 Callable的任务执行后可以返回值,而Runable的任务是不能返回值的。
3、 Call()方法可以抛出异常,run()方法不可以抛出异常。
4、 运行Callable任务可以拿到一个Future对象,标识异步计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
一、通过实现Runnable接口来创建线程
public class RunnableTest {
public static void main(String[] args) {
testRunnable runnable = new testRunnable();
Thread thread = new Thread(runnable,"Runnable");
thread.start();
}
}
class testRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 实现Runnable接口,创建的线程");
}
}
二、通过继承Thread类来创建线程
public class TestThread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"继承Thread创建线程");
}
}
public class ThreadTest {
public static void main(String[] args) {
TestThread thread = new TestThread();
Thread threads = new Thread(thread,"extends Thread");
threads.start();
}
}
三、通过实现Callable接口来创建线程
public class TestCallables {
public static void main(String[] args) {
TestCallable testCallable = new TestCallable();
FutureTask<Integer> future=new FutureTask<Integer>((Callable<Integer>)()->{
System.out.println(Thread.currentThread().getName()+"这是实现Callable接口创建的线程");
return 5;
}
);
new Thread(future,"Callable:").start();
try {
System.out.println("子线程的返回值:"+future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}//get()方法会阻塞,直到子线程执行结束才返
}
}
四、 通过(Executor框架)线程池创建线程
public class TestExecutorService {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute((Runnable)()->{
System.out.println(Thread.currentThread().getName()+" : 使用线程池,创建的线程");
}
);
executorService.shutdown();
}
}