Java面试必备知识查缺补漏(一)

写再前面,希望大家在看下面的具体内容之前,对照目录依次询问自己是否清楚这个问题。看完之后,在对照我写的查看相关知识点。本人水平有限,有些地方写的可能不够全面或者有异议。欢迎各位大佬们指出来,给我一个改正的机会、学习的机会,让我们一起进步,谢谢。


线程池的常用的参数和含义

  • corePoolSize:核心线程数
  • maxinumPoolSize:最大线程数
  • keepAliveTime:线程不执行任务时保持存活的时间
  • TimeUnit:keepAliveTime的时间单位
  • ThreadFactory:线程工厂

线程池的拒绝策略

  • AbortPolicy:线程池的默认策略。使用该策略时,如果线程池队列满了丢掉这个任务并且抛出RejectedExecutionException异常。
  • DiscardPolicy:如果线程池队列满了,会直接丢掉这个任务并且不会有任何异常。
  • DiscardOldestPolicy:丢弃最老的。也就是说如果队列满了,会将最早进入队列的任务删掉腾出空间,再尝试加入队列。
  • CallerRunsPolicy:使用此策略,如果添加到线程池失败,那么主线程会自己去执行该任务,不会等待线程池中的线程去执行。
  • 自定义执行策略:如果以上策略都不符合业务场景,那么可以自己定义一个拒绝策略,只要实现RejectedExecutionHandler接口,并且实现rejectedExecution方法就可以了。

Java线程停止的几种方法和对比

  • volatile + 标志位:使用退出标志,使线程正常退出,也就是当 run() 方法完成后线程中止。定义一个用volatile修饰的成员变量来控制线程的停止,这点是利用了volatile修饰的成员变量可以在多线程之间达到共享,也就是可见性来实现的。
  • stop():过期了的API,不建议使用的,因为stop()在结束一个线程时并不会保证线程的资源正常释放,会导致程序可能会出现一些不确定的状态。
  • interrupt():当其他线程调用当前线程的interrupt方法时,即设置了一个标识,表示当前线程可以中断了,至于什么时候中断,取决于当前线程。

为什么弃用stop?
调用 stop() 方法会立刻停止 run() 方法中剩余的全部工作,包括在 catch 或 finally 语句中的,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。
调用 stop() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题。

ThreadLocal原理

ThreadLocal提供一个线程(Thread)局部变量,访问到某个变量的每一个线程都拥有自己的局部变量。简单来说,ThreadLocal就是想在多线程环境下去保证成员变量的安全。

  • ThreadLocal的实现原理:在每个线程中维护一个Map,键是ThreadLocal类型,值是Object类型。当想获取ThreadLocal的值时,就从当前线程中拿出Map,然后在把ThreadLocal本身作为键从Map中拿出值返回。

ThreadLocal和Synchonized区别

ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的差别。

  • synchronized是利用锁的机制,使变量或代码块在某一时该仅仅能被一个线程访问。而ThreadLocal为每个线程都提供了变量的副本,使得每个线程在某一时间访问到的并非同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时可以获得数据共享。

Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。

局部变量存在线程安全问题吗

  • 不存在原因局部变量放在栈帧里,栈帧是线程私有的。局部变量的作用域是方法内部,局部变量和方法的生命周期一样(同生共死),一个变量如果想跨越方法的边界,就必须创建在堆里。每个线程都有自己独立的调用栈,局部变量保存在线程各自的调用栈里面,不会共享,没有共享就没有安全问题。

公平锁和非公平锁

简单的来说,如果一个线程组里,能保证每个线程都能拿到锁,那么这个锁就是公平锁。相反,如果保证不了每个线程都能拿到锁,也就是存在有线程饿死,那么这个锁就是非公平锁

  • 公平锁中,如果有另一个线程持有锁或者有其他线程在等待队列中等待这个所,那么新发出的请求的线程将被放入到队列中。
  • 非公平锁中,只有当锁被某个线程持有时,新发出请求的线程才会被放入队列中(此时和公平锁是一样的)。当前的锁状态没有被占用时,当前线程可以直接占用,而不需要判断当前队列中是否有等待线程。
  • 公平锁和非公平锁的差别在于非公平锁会有更多的机会去抢占锁。

ReentrantLock和synchronized区别

  • 两者加锁方式都是阻塞式的同步,也就是如果一个线程获得了对象锁,进入了同步块,其他访问该同步块的线程都必须阻塞在同步块外面等待,而进行线程阻塞和唤醒的代价是比较高的(操作系统需要在用户态与内核态之间来回切换,代价很高,不过可以通过对锁优化进行改善)。
  • synchronized是java语言的关键字,需要jvm实现。而ReentrantLock它是JDK 1.5之后提供的Java API层面的互斥锁,需要lock()和unlock()方法配合try/finally语句块来完成。
  • 在synchronized优化以前,synchronized的性能是比ReenTrantLock差很多的,但是自从synchronized引入了锁升级后,两者的性能就差不多了。
  • ReentrantLock默认是非公平锁,可通过构造传参(true)改为公平锁。而synchronized是公平锁。

你知道的越多,你不知道的越多。
有道无术,术尚可求,有术无道,止于术。
如有其它问题,欢迎大家留言,我们一起讨论,一起学习,一起进步

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值