Java习题
1、说说 synchronized 关键字和 volatile 关键字的区别
- synchronized 关键字和 volatile 关键字是两个互补的存在,而不是对立的存在!
- volatile 关键字是线程同步的轻量级实现,所以 volatile 性能肯定比 synchronized 关键字要好。但是 volatile 关键字只能用于变量而 synchronized 关键字可以修饰方法以及代码块。
- volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都能保证。volatile 关键字主要用于解决变量在多个线程之间的可见性,而 synchronized 关键字解决的是多个线程之间访问资源的同步性。
2、如何保证一个线程执行完再执行第二个线程?
使用 join() 方法,等待上一个线程的执行完之后,再执行当前线程。
示例代码:
//java
Thread joinThread = new Thread(() -> {
try {
System.out.println("执行前");
Thread.sleep(1000);
System.out.println("执行后");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
joinThread.start();
joinThread.join();
System.out.println("主程序");
3、说说 sleep() 方法和 wait() 方法区别和共同点?
- sleep() 方法来自 Thread 类,wait() 方法来自 Object 类。
- sleep() 方法是直接让线程休眠,wait() 方法是让当前访问资源的线程休眠。
- sleep() 方法没有释放锁,而 wait() 方法释放了锁 ,两者都可以暂停线程的执行。
- wait() 通常被用于线程间交互/通信, sleep() 通常被用于暂停执行。
- wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同⼀个对象上的 notify() 或 者 notifyAll() 方法。
- sleep() 方法执行完成后,线程会根据时间自动苏醒。
4、启动线程为什么要调用 start 而不是 run?
- 调 run 方法就是普通方法的调用,相当于在主线程中让一个对象的方法运行,而调用 start 方法才是开启子线程,让它去争夺 CPU 资源,拿到资源后,会自动执行 run 方法。
5、在 ThreadPool 中 submit() 和 execute() 有什么区别?
submit() 和 execute() 都是用来执行线程池的,只不过使用 execute() 执行线程池不能有返回方法,而使用 submit() 可以使用 Future 接收线程池执行的返回值。
submit() 方法源码(JDK 8)如下:
//java
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
execute() 源码(JDK 8)如下:
//java
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//..... 其他
}
6、说一下 ThreadPoolExecutor 都需要哪些参数?
-
ThreadPoolExecutor 最多包含以下七个参数:
-
corePoolSize:线程池中的核心线程数
-
maximumPoolSize:线程池中最大线程数
-
keepAliveTime:闲置超时时间
-
unit:keepAliveTime 超时时间的单位(时/分/秒等)
-
workQueue:线程池中的任务队列
-
threadFactory:为线程池提供创建新线程的线程工厂
-
rejectedExecutionHandler:线程池任务队列超过最大值之后的拒绝策略
7、在线程池中 shutdownNow() 和 shutdown() 有什么区别?
shutdownNow() 和 shutdown() 都是用来终止线程池的,它们的区别是,使用 shutdown() 程序不会报错,也不会立即终止线程,它会等待线程池中的缓存任务执行完之后再退出,执行了 shutdown() 之后就不能给线程池添加新任务了;shutdownNow() 会试图立马停止任务,如果线程池中还有缓存任务正在执行,则会抛出 java.lang.InterruptedException: sleep interrupted 异常。