Java基础知识记录-20220317
Java基础知识记录-20220317
spring Bean的生命周期
1.实例化Bean实例
2.设置对象属性
3.检查Aware的相关接口并设置相关依赖
4.BeanPostProcessor前置处理
5.是否实现InitializingBean接口
6.是否配置自定义的init-method
7.BeanPostProcessor后置处理
8.注册Destruction相关回调接口
9.是否实现DisposableBean接口
10.是否配置自定义的destory-method
spring中都用到了哪些设计模式
1.简单工厂: BeanFactory
2.工厂方法: FactoryBean
3.单例模式: DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
4.适配器模式: HandlerAdapter
5.装饰器模式
6.代理模式
7.观察者模式 spring中的事件驱动
8.策略模式 Resource
9.模版方法 JdbcTemplate
spring中的单例是如何实现的
相关方法
org.springframework.beans.factory.BeanFactory#getBean(java.lang.String)
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
单例获取方法
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
BeanFactory和FactoryBean的区别
- BeanFactory:负责生产和管理Bean的一个工厂接口,提供一个Spring Ioc容器规范,
- FactoryBean: 一种Bean创建的一种方式,对Bean的一种扩展。对于复杂的Bean对象初始化创建使用其可封装对象的创建细节。
阻塞队列是线程安全的吗
阻塞队列是线程安全的,因为在它的实现类中获取数据和插入数据都是加ReentrantLock锁的
//以ArrayBlockingQueue 的take和put方法为例
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
ReentrantLock底层都用到了哪些东西
AQS 、CLH 、CAS
ReentrantLock 是可重入锁吗
ReentrantLock是可重入锁
ReentrantLock中的公平锁和非公平锁的区别
公平锁和非公平锁,主要是在方法 tryAcquire 中,是否 有 !hasQueuedPredecessors() 判断
//公平锁
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//公平锁和非公平锁的区别,公平锁会判断当前队列中没有其他线程在等待锁资源
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
//非公平锁
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
ReentrantLock中的Sync重写了AQS的哪两个方法
//这是独占式释放同步状态的方法,让那些等待获取同步状态的线程能够有机会获取同步状态
java.util.concurrent.locks.AbstractQueuedSynchronizer#tryRelease
//这个方法用来判断当前同步器是否在独占模式下被线程占用,它会取出占用的线程和当前线程做个比较,看下是否相等。
java.util.concurrent.locks.AbstractQueuedSynchronizer#isHeldExclusively
ReentrantLock中的状态变量为什么不使用AtomicInteger
代码漏洞
1.以下代码有什么目的? 有什么严重的bug?
private int sumSubString(String a, String b){
int sub = 0;
while (a.contains(b)) {
sub++;
a = a.replaceFirst(b, " ");
}
return sub;
}
解惑
1.上面的代码为了统计字符串a包含多少个字符串b
2.上面的代码执行,会在以下两种情况下死循环
public class CountStringTest {
private int sumSubString(String a, String b){
int sub = 0;
while (a.contains(b)) {
sub++;
a = a.replaceFirst(b, " ");
}
return sub;
}
//1.第一种情况a中有空格,b中也有空格
@Test(timeout = 5L)
public void testSumSubString(){
String a = "hello world";
String b = " ";
int i = new CountStringTest().sumSubString(a, b);
System.out.println(i);
}
//碰到了转义字符
@Test
public void testSumSubString2(){
String a = "hello\\rworld";
String b = "\\r";
int i = new CountStringTest().sumSubString(a, b);
System.out.println(i);
}
}
作者:努力为明天
-------------------------------------------
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!