- 1.什么是进程?是什么线程?进程和线程的关系?
- 2.并行和并发的区别?
- 3.多线程的优缺点(为什么使用多线程、多线程会引发什么问题)
- 4.线程的上下文切换
- 5.Java中守护线程和用户线程的区别?
- 6.线程死锁是如何产生的,如何避免
- 7.用Java实现死锁,并给出避免死锁的解决方案
- 8.Java中的死锁、活锁、饥饿有什么区别?
- 9.线程的生命周期和状态
- 10.创建线程一共有哪几种方法?
- 11.runnable 和 callable 有什么区别?
- 12.线程的run()和start()有什么区别?为什么调用start()方法时会执行run()方法,而不直接执行run()方法?
- 13.线程同步以及线程调度相关的方法有哪些?
- 14.线程的sleep()方法和yield()方法有什么不同?
- 15.sleep()方法和wait()方法的区别?
- 16.wait()方法一般在循环块中使用还是if块中使用?
- 17.线程通信的方法有哪些?
- 18.为什么wait()、notify()、notifyAll()被定义在Object类中而不是在Thread类中?
- 19.为什么wait(),notify()和notifyAll()必须在同步方法或者同步块中被调用?
- 20.为什么Thread类的sleep()和yield()方法是静态的?
- 21.如何停止一个正在运行的线程?
- 22.如何唤醒一个阻塞的线程?
- 23.Java如何实现两个线程之间的通信和协作?
- 24.同步方法和同步方法块哪个效果更好?
- 25.什么是线程同步?什么是线程互斥?他们是如何实现的?
- 26.在Java程序中如何保证线程的运行安全?
- 27.线程类的构造方法、静态块是被哪个线程调用的?
- 28.一个线程运行时异常会发生什么?线程数量过多会造成什么异常?
- 29.三个线程T1、T2、T3,如何让他们按顺序执行?
- 30.什么是synchronized关键字?
- 31.Java内存的可见性
- 32.synchronized关键字三大特性是什么?
- 33.synchronized关键字可以实现什么类型的锁?
- 34.synchronized关键字的使用方法
- 35.synchronized关键字的底层原理
- 36.jdk1.6为什么要对synchronized进行优化?做了哪些优化?
- 37.了解锁消除吗?了解锁粗化吗?
- 38.当线程1进入到一个对象的synchronized方法A后,线程2是否可以进入到此对象的synchronized方法B?
- 39.synchronized和volatile的区别?
- 40.synchronized和Lock的区别?
- 41.volatile的作用是什么?volatile的特性有哪些?
- 42.Java内存的可见性问题
- 43.为什么代码会重排序?
- 44.重排序会引发什么问题?
- 45.as-if-serial规则和happens-before规则的区别?
- 46.voliatile的实现原理?volatile实现内存可见性原理?
- 47.volatile如何实现有序性
- 48.编译器对内存屏障插入策略的优化
- 49.volatile能使一个非原子操作变成一个原子操作吗?
- 50.volatile和synchronized的区别?
- 51.什么是ConcurrentHashMap?相比于HashMap和HashTable有什么优势?
- 52.java中ConcurrentHashMap是如何实现的?
- 53.ConcurrentHashMap结构中变量使用volatile和final修饰有什么作用?
- 54.ConcurrentHashMap有什么缺点?
- 55.ConcurrentHashMap默认初始容量是多少?每次扩容为原来的几倍?
- 56.ConCurrentHashMap的key,value是否可以为null?为什么?HashMap中的key、value是否可以为null?
- 57.ConCurrentHashmap在JDK1.8中,什么情况下链表会转化为红黑树?
- 58.ConcurrentHashMap在JDK1.7和JDK1.8版本中的区别?
- 59.ConcurrentHashMap迭代器是强一致性还是弱一致性?
- 60.什么是ThreadLocal?有哪些应用场景?
- 61.ThreadLocal原理和内存泄露?
- 62.什么是线程池?为什么使用线程池?
- 63.线程池创建的几种方法
- 64.ThreadPoolExecutor构造函数的重要参数分析
- 65.ThreadPoolExecutor的饱和策略(拒绝策略)
- 66.线程池的执行流程
- 67.execute()方法和submit()方法的区别
- 68.什么是CAS?
- 69.CAS存在的问题及优点
- 70.Atomic原子类
- 71.什么是AQS?AQS的原理是什么?
- 72.AQS的资源共享方式有哪些?
- 73.如何使用AQS自定义同步器?
73.如何使用AQS自定义同步器?
AQS的底层使用了模板方法模式,自定义同步器只需要两步:第一,继承AbstractQueuedSynchronizer
,第二,重写以下几种方法:
- isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
- tryAcquire(int):独占方式,尝试获取资源。
- tryRelease(int):独占方式,尝试释放资源。
- tryAcquireShared(int):共享方式,尝试获取资源。负数表示失败,0表示成功,但无剩余可用资源,正数表示成功并且有剩余资源
- tryReleaseShared(int):共享方式,尝试释放资源
下面举例说明,以独占式的ReentrantLock
为例,state
初始状态为0,表示未锁定状态。A线程进行lock()
时,会调用tryAcquire()
独占该锁并将state+1
。此后,其他线程再调用tryAcquire()
时就会失败,直到A线程unlock()
到state=0(即释放锁)为止,其它线程才有机会获取该锁。当然,释放锁之前,A线程自己是可以重复获取此锁的(state会累加),这就是可重入的概念。但要注意,获取多少次就要释放多么次,这样才能保证state是能回到零态的。
再以共享使得CountDownLatch
以例,任务分为N个子线程去执行,state也初始化为N(注意N要与线程个数一致)。这N个子线程是并行执行的,每个子线程执行完后countDown()
一次,state会CAS减1。等到所有子线程都执行完后(即state=0),会unpark()
主调用线程,然后主调用线程就会从await()
函数返回,继续后余动作。
一般来说,自定义同步器要么是独占方法,要么是共享方式,他们也只需实现tryAcquire-tryRelease
、tryAcquireShared-tryReleaseShared
中的一种即可。但AQS也支持自定义同步器同时实现独占和共享两种方式,如ReentrantReadWriteLock
。
这部内容分参考博客:https://www.cnblogs.com/waterystone/p/4920797.html
本站链接:https://www.mianshi.online,如需勘误或投稿,请联系微信:lurenzhang888
点击面试手册,获取本站面试手册PDF完整版