欢迎大家来到IT世界,在知识的湖畔探索吧!
一、如何停止一个线程
- 使用volatile变量终止正常运行的线程 + 抛异常法/Return法
- 组合使用interrupt方法与interruptted/isinterrupted方法终止正在运行的线程 + 抛异常法/Return法
- 使用interrupt方法终止 正在阻塞中的 线程
二、何为线程安全的类?
在线程安全性的定义中,最核心的概念就是 正确性。当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么这个类就是线程安全的。
三、为什么线程通信的方法wait(), notify()和notifyAll()被定义在Object类里?
Object lock = new Object(); synchronized (lock) { lock.wait(); ... }
欢迎大家来到IT世界,在知识的湖畔探索吧!
Wait-notify机制是在获取对象锁的前提下不同线程间的通信机制。在Java中,任意对象都可以当作锁来使用,由于锁对象的任意性,所以这些通信方法需要被定义在Object类里。
四、为什么wait(), notify()和notifyAll()必须在同步方法或者同步块中被调用?
wait/notify机制是依赖于Java中Synchronized同步机制的,其目的在于确保等待线程从Wait()返回时能够感知通知线程对共享变量所作出的修改。如果不在同步范围内使用,就会抛出java.lang.IllegalMonitorStateException的异常。
五、并发三准则
- 异常不会导致死锁现象:当线程出现异常且没有捕获处理时,JVM会自动释放当前线程占用的锁,因此不会由于异常导致出现死锁现象,同时还会释放CPU;
- 锁的是对象而非引用;
- 有wait必有notify;
六、如何确保线程安全?
在Java中可以有很多方法来保证线程安全,诸如:
- 通过加锁(Lock/Synchronized)保证对临界资源的同步互斥访问;
- 使用volatile关键字,轻量级同步机制,但不保证原子性;
- 使用不变类 和 线程安全类(原子类,并发容器,同步容器等)。
七、volatile关键字在Java中有什么作用
volatile的特殊规则保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新,即保证了内存的可见性,除此之外还能 禁止指令重排序。此外,synchronized关键字也可以保证内存可见性。
指令重排序问题在并发环境下会导致线程安全问题,volatile关键字通过禁止指令重排序来避免这一问题。而对于Synchronized关键字,其所控制范围内的程序在执行时独占的,指令重排序问题不会对其产生任何影响,因此无论如何,其都可以保证最终的正确性。
八、ThreadLocal及其引发的内存泄露
ThreadLocal是Java中的一种线程绑定机制,可以为每一个使用该变量的线程都提供一个变量值的副本,并且每一个线程都可以独立地改变自己的副本,而不会与其它线程的副本发生冲突。
每个线程内部有一个 ThreadLocal.ThreadLocalMap 类型的成员变量 threadLocals,这个 threadLocals 存储了与该线程相关的所有 ThreadLocal 变量及其对应的值,也就是说,ThreadLocal 变量及其对应的值就是该Map中的一个 Entry,更直白地,threadLocals中每个Entry的Key是ThreadLocal 变量本身,而Value是该ThreadLocal变量对应的值。
(1). ThreadLocal可能引起的内存泄露
下面是ThreadLocalMap的部分源码,我们可以看出ThreadLocalMap里面对Key的引用是弱引用。那么,就存在这样的情况:当释放掉对threadlocal对象的强引用后,map里面的value没有被回收,但却永远不会被访问到了,因此ThreadLocal存在着内存泄露问题。
欢迎大家来到IT世界,在知识的湖畔探索吧! static class ThreadLocalMap { /** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows. */ static class Entry extends WeakReference<ThreadLocal> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal k, Object v) { super(k); value = v; } } ... }
看下面的图示, 实线代表强引用,虚线代表弱引用。每个thread中都存在一个map,map的类型是上文提到的ThreadLocal.ThreadLocalMap,该map中的key为一个ThreadLocal实例。这个Map的确使用了弱引用,不过弱引用只是针对key,每个key都弱引用指向ThreadLocal对象。一旦把threadlocal实例置为null以后,那么将没有任何强引用指向ThreadLocal对象,因此ThreadLocal对象将会被 Java GC 回收。但是,与之关联的value却不能回收,因为存在一条从current thread连接过来的强引用。 只有当前thread结束以后, current thread就不会存在栈中,强引用断开,Current Thread、Map及value将全部被Java GC回收。
所以,得出一个结论就是:只要这个线程对象被Java GC回收,就不会出现内存泄露。但是如果只把ThreadLocal引用指向null而线程对象依然存在,那么此时Value是不会被回收的,这就发生了我们认为的内存泄露。比如,在使用线程池的时候,线程结束是不会销毁的而是会再次使用的,这种情形下就可能出现ThreadLocal内存泄露。
Java为了最小化减少内存泄露的可能性和影响,在ThreadLocal进行get、set操作时会清除线程Map里所有key为null的value。所以最怕的情况就是,ThreadLocal对象设null了,开始发生“内存泄露”,然后使用线程池,线程结束后被放回线程池中而不销毁,那么如果这个线程一直不被使用或者分配使用了又不再调用get/set方法,那么这个期间就会发生真正的内存泄露。因此,最好的做法是:在不使用该ThreadLocal对象时,及时调用该对象的remove方法去移除ThreadLocal.ThreadLocalMap中的对应Entry。
九、什么是死锁(Deadlock)?如何分析和避免死锁?
死锁是指两个以上的线程永远阻塞的情况,这种情况产生至少需要两个以上的线程和两个以上的资源。
分析死锁,我们需要查看Java应用程序的线程转储。我们需要找出那些状态为BLOCKED的线程和他们等待的资源。每个资源都有一个唯一的id,用这个id我们可以找出哪些线程已经拥有了它的对象锁。下面列举了一些JDK自带的死锁检测工具:
(1). Jconsole:JDK自带的图形化界面工具,主要用于对 Java 应用程序做性能分析和调优。
(2). Jstack:JDK自带的命令行工具,主要用于线程Dump分析。
(3). VisualVM:JDK自带的图形化界面工具,主要用于对 Java 应用程序做性能分析和调优。
十、什么是Java Timer类?如何创建一个有特定时间间隔的任务?
Timer是一个调度器,可以用于安排一个任务在未来的某个特定时间执行或周期性执行。TimerTask是一个实现了Runnable接口的抽象类,我们需要去继承这个类来创建我们自己的定时任务并使用Timer去安排它的执行。
Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { System.out.println("abc"); } }, 200000 , 1000);
十一、什么是线程池?如何创建一个Java线程池?
十二、CAS : CAS自旋volatile变量,是一种很经典的用法。
十三、AQS : 队列同步器
十四、Java Concurrency API中的Lock接口(Lock interface)是什么?对比同步它有什么优势?
十五、Condition
十六、什么是阻塞队列?如何使用阻塞队列来实现生产者-消费者模型?
十七、同步容器(强一致性)
十八、什么是CopyOnWrite容器(弱一致性)?
十九、ConcurrentHashMap (弱一致性)
二十、happens-before
二十一、锁优化技术
二十二、主线程等待子线程运行完毕再运行的方法
最后
由于篇幅过长的原因,为了不影响大家的阅读效果,文中没有给到所有的答案。我这里以文件的形式整理好了,需要借阅的程序员朋友可以免费来领取。
面试文件获取方式:
转发+关注我,后台私信回复【资料】免费领取面试资料(助你金三银四能跳槽涨薪)
收集了还有你不知道的其它面试题(springboot、mybatis、并发、java中高级面试总结等)
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/36760.html