面试个人小结

核心提示我总结了最近面试的一些常见面试题,和大家分享一下创建线程池有哪几种方式?线程池创建有七种方式,最核心的是最后一种:newSingleThreadExecutor:它的特点在于工作线程数目被限制为 1,操作一个无界的工作队列,所以它保证了所有

最近总结了一些常见的面试问题,分享给大家。

创建线程池有哪些方法?

创建线程池有七种方法,核心是最后一种:

NewSingleThreadExecutor:其特点是工作线程数限定为1,运行一个无界的工作队列,所以保证所有任务都按顺序执行,最多会有一个任务处于活动状态,不允许用户更改线程池实例,所以可以避免更改线程数;

NewCachedThreadPool:是一种用于处理大量短期工作任务的线程池。它有几个与众不同的特点:它会尝试缓存线程并重用它们,当未缓存的线程可用时,它会创建新的工作线程;如果线程空闲时间超过60秒,将被终止并从缓存中移除;当长时间空闲时,这个线程池不会消耗任何资源。它在内部使用SynchronousQueue作为工作队列;

NewFixedThreadPool:重用指定数量的线程,在其后面使用一个无限制的工作队列。任何时候最多有n个线程处于活动状态。这意味着如果任务数超过活动队列数,它将等待空空闲线程出现在工作队列中;如果一个工作线程存在,将创建一个新的工作线程来弥补指定数量的n个线程;;

newsingletthreadschedule executor:创建一个单线程池,返回ScheduledExecutorService,可以定时或者周期性的调度工作;

NewScheduledThreadPool:类似于NewsingleThreadScheduleExecutor,它创建一个ScheduledExecutorService,可以定期或周期性地调度作业。区别在于有单个工作线程还是多个工作线程;

NewWorkStealingPool:这是一个经常被忽略的线程池。Java 8刚好加入了这种创建方式。内部会内置ForkJoinPool,采用偷功算法并行处理任务,不保证处理顺序。

ThreadPoolExecutor:是线程池最原始的创建。以上1-3种创建方法都是ThreadPoolExecutor的封装。

notify和notifyAll有什么区别?

NotifyAll会唤醒所有线程,notify之后会唤醒一个线程。调用notifyAll后,所有线程都将从等待池移动到锁池,然后竞争锁。如果竞争成功,它将继续执行。如果不成功,它将留在锁池中,等待锁被释放,然后再次竞争。Notify只会唤醒一个线程,这个线程是虚拟机控制的。

shimo.im/docs/RKAWVMrjv9frVek8执行后得到结果。

睡觉和等待有什么区别?

类区别:睡眠来自线程,等待来自对象。

解锁:睡眠不解锁;等等,打开锁。

用法:睡眠时间会自动恢复;Wait可以使用notify/notifyAll直接唤醒。

如何防止死锁?尽量使用tryLock的方法设置超时,可以退出防止死锁。

尝试使用Java。util。concurrent并发类,而不是您自己手写锁。

尽量降低锁的粒度,尽量不要对几个函数使用同一个锁。

最小化同步代码块的数量。

shimo.im/docs/RKAWVMrjv9frVek8执行后得到结果。

线程池的状态是什么?正在运行:这是最正常的状态,接受新任务,处理等待队列中的任务。

关闭:不接受新任务提交,但等待队列中的任务将继续处理。

STOP:不接受新的任务提交,停止处理等待队列中的任务,并中断正在执行任务的线程。

整理:所有任务被销毁,工作计数为0。当线程池的状态转换为整理状态时,将执行终止的钩子方法。

Terminated:在terminated方法结束后,线程池的状态将变成这样。

有哪些创建线程的方法?创建线程有三种方式:

继承Thread重写run方法;

实现Runnable接口;

实现可调用接口。

runnable和callable有什么区别?Runnable没有返回值,callable可以得到一个返回值,callable可以看作是对runnable的补充。

线程池中的提交和执行方法有什么区别?执行:只能执行类型为Runnable的任务。

提交:您可以执行可运行和可调用类型的任务。

可调用类型的任务可以获得执行的返回值,而可运行的执行没有返回值。

线程的运行和开始有什么区别?start方法用于启动线程,run方法用于执行线程的运行时代码。Run可以重复调用,start只能调用一次。

迭代器迭代器是什么?迭代器接口提供了一个接口来遍历任何集合。我们可以使用迭代器方法从集合中获取迭代器实例。迭代器取代了Java集合框架中的枚举。迭代器允许调用方在迭代过程中删除元素。

迭代器怎么用?有什么特点?Iterator更安全,因为它可以确保当当前遍历的set元素发生变化时,会抛出ConcurrentModificationException异常。

迭代器和ListIterator有什么区别?迭代器可以遍历集合和列表集合,而ListIterator只能遍历列表。迭代器只能单向遍历,而ListIterator可以双向遍历。ListIterator继承了Iterator接口,然后增加了一些额外的功能,比如增加一个元素,替换一个元素,获取前一个或后一个元素的索引位置。最终打印结果:shimo.im/docs/RKAWVMrjv9frVek8

如何保证一个集合不能被修改?

可以使用collections . un modified集合方法创建只读集合,这样任何更改集合的操作都会引发java.lang.unsupported操作异常。

并行和并发有什么区别?并行:多个处理器或多核处理器同时处理多个任务。

并发:多个任务按照细分的时间片依次在同一个CPU核上执行。从逻辑上讲,这些任务是同时执行的。

并发=两个队列和一台咖啡机。

并行=两个队列和两台咖啡机。

线程和进程有什么区别?一个程序至少有一个进程,一个进程至少有一个线程,一个进程可以有多个线程来提高程序的执行速度。

什么是守护线程?守护进程是一个在后台运行的特殊进程。它独立于控制终端,定期执行某些任务或等待处理某些事件。垃圾收集线程是Java中一种特殊的守护线程。

线程的状态是什么?

线程状态:

尚未开始新建。

RUNNABLE正在运行。

被阻止被阻止

等待永久等待状态

TIMED_WAITING等待指定时间再次被唤醒的状态。

终止执行已完成。

执行后得到结果:shimo.im/docs/RKAWVMrjv9frVek8

如何保证Java程序中多线程的安全性?方法1:使用安全类,比如java.util.concurrent下的安全类。

方法2:使用自动同步锁。

方法三:使用手动锁。

多线程中同步锁升级的原理是什么?同步锁升级原理:锁对象的对象头中有一个threadid字段。第一次访问锁对象时,threadid是空。jvm让它持有偏置锁,并将threadid设置为它的线程id。再次进入时,它会先判断threadid与其Threadid是否一致。如果一致,可以直接用这个对象;如果不一致,将偏置锁升级为轻量锁,旋转一定次数获得锁。经过一定次数后,如果没有正常获得要使用的对象,锁就会从轻量级锁升级为重量级锁,这个过程就构成了同步锁的升级。

锁升级的目的:锁升级的目的是减少锁带来的性能消耗。Java 6之后优化了同步实现,将偏置锁升级为轻量级锁,再升级为重量级锁,减少了锁带来的性能消耗。

什么是死锁?当线程A持有独占锁A并试图获取独占锁B,而线程B持有独占锁B并试图获取独占锁A时,AB的两个线程会互相阻塞对方的锁,这就是所谓的死锁。

什么是ThreadLocal?有哪些使用场景?ThreadLocal为每个使用该变量的线程提供了一个独立的变量副本,因此每个线程都可以独立地更改自己的副本,而不会影响其他线程的相应副本。

ThreadLocal的经典使用场景是数据库连接和会话管理。

说说同步底层实现的原理?

Synchronized由一对monitorenter/monitorexit指令实现,monitor对象是同步的基本单元。在Java 6之前,monitor的实现完全依赖于操作系统中的互斥体。因为它需要从用户模式切换到内核模式,同步操作是一种低性能的不加选择的重量级操作。但是在Java 6中,Java虚拟机进行了大刀阔斧的改进,提供了三种不同的monitor实现,即三种不同的锁:偏置锁、轻量级锁和重量级锁,大大提高了其性能。

同步和易变的区别是什么?

Volatile是可变修饰符;Synchronized是修饰类、方法、代码段。

Volatile只能实现变量的修改可见性,不能保证原子性;Synchronized可以保证变量的可见性和原子性。

Volatile不会造成线程阻塞;同步可能会导致线程阻塞。

synchronized和Lock有什么区别?

Synchronized可以锁定类、方法和代码块;而lock只能锁定代码块。

Synchronized不需要手动获取和释放锁,所以很容易使用。如果出现异常,锁会自动释放,不会造成死锁。锁需要自己上锁和开锁。如果使用不当,释放锁而不解锁会导致死锁。

通过锁可以知道自己是否成功获取了锁,而synchronized则不能。

synchronized和ReentrantLock有什么区别?

synchronized的早期实现是低效的。与ReentrantLock相比,大多数场景的性能相差很大,但在Java 6中synchronized上有很多改进。

主要区别如下:

ReentrantLock使用起来很灵活,但是必须有一个协同动作来释放锁;

ReentrantLock必须手动获取和释放锁,而synchronized不需要手动释放和打开锁;

ReentrantLock只适用于代码块锁,而synchronized可以用来修饰方法、代码块等。

说说原子的原理?

Atomic主要使用CAS、volatile和native方法来保证原子操作,从而避免了synchronized的高开销,大大提高了执行效率。

什么是反思?

在运行状态下,反射可以知道任何类的所有属性和方法。对于任何对象,都可以调用它的任何方法和属性;这种动态获取信息,动态调用对象方法的功能,被称为Java语言的反射机制。

什么是Java序列化?什么情况下需要序列化?

Java序列化是将各种对象的状态保存在内存中,并可以再次读出保存的对象状态。

以下情况需要Java序列化:

当您希望将内存中对象的状态保存到文件或数据库中时;

当你想用套接字在网络上传输对象时;

当你想通过RMI传输对象时。

什么是动态代理?有哪些应用?动态代理是在运行时动态生成的代理类。

动态代理应用包括spring aop、hibernate数据查询、测试框架的后端mock和rpc、Java标注对象获取等。

如何实现动态代理?JDK本地动态代理和cglib动态代理。JDK原生动态代理是基于接口实现的,而cglib是基于继承当前类的子类实现的。

仅此而已。有兴趣的可以私信我。我还有一些资料要发给你~

 
友情链接
鄂ICP备19019357号-22