关于多线程的面试题
使用Runnalbe还是Thread?
JAVA里面允许调用多个接口,但是不允许多继承,所以实现Runable接口更好
Runnable和Callable有什么不同?
Runnable和Callable都代表那些要在不同的线程中执行的任务
Callable是在JDK1.5增加的。它们的主要区别是Callable的 call() 方法可以返回值和抛出异常(返回Future对象)
Thread类中的start() 和 run() 方法有什么区别?
start()方法被用来启动新创建的线程,而且start()内部调用了run()方法
当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程
为什么要使用线程池
创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限
在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程(JDK1.5开始提供Excutor)
提交任务时,线程池队列已满。会时发会生什么?
一个任务不能被调度执行那么ThreadPoolExecutor’s submit()方法将会抛出一个RejectedExecutionException异常
不是会阻塞直到线程池队列有空位
线程池中submit()和 execute()方法有什么区别?
两个方法都可以向线程池提交任务
execute()方法的返回类型是void,它定义在Executor接口中
submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口
什么是FutureTask?
FutureTask表示一个可以取消的异步运算
有启动和取消运算、查询运算是否完成和取回运算结果等方法。只有当运算完成的时候结果才能取回,如果运算尚未完成get方法将会阻塞。
一个FutureTask对象可以对调用了Callable和Runnable的对象进行包装,由于FutureTask也是调用了Runnable接口所以它可以提交给Executor来执行
如何创建一个线程池?
class Worker implements Runnable {
int id;
public Worker(int i){
this.id = i;
}
@Override
public void run(){
//...
}
}
public class Main(){
public void create(){
ExecutorService executor = Executors.newFixedThreadPool(2);
for(int i=1; i<2; i++){
Runnable worker = new Worker(i);
executor.execute(worker);
}
}
}