Java笔记
回答问题
是什么,为什么有它,解决什么问题,怎么解决?
读取列表
public class ReadList {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String line = bufferedReader.readLine();
int[] nums = stringToIntegerArray(line);
System.out.println(Arrays.toString(nums));
int k = Integer.parseInt(bufferedReader.readLine());
System.out.println(k);
}
private static int[] stringToIntegerArray(String line) {
line = line.trim();
line = line.substring(1,line.length()-1);
String[] strs = line.split(",");
int[] output = new int[strs.length];
for(int i=0;i<strs.length;i++) {
output[i] = Integer.parseInt(strs[i].trim());
}
return output;
}
/**
* [1,2,3 ,4,6 ]
* [1, 2, 3, 4, 6]
* 5
* 5
*/
}
concurrenthashmap
多线程分配任务
扩容时存取
JVM gc root
堆、方法区是线程共享的,栈、本地方法栈、程序计数器是线程独有的。
JVM在垃圾回收的时候,要先找到垃圾对象,也就是没有引用的对象,但是直接找垃圾不好找,就反过来先找正常对象,这就需要从一些根开始,根据根的引用找到正常对象。这些根特征就是会引用其他对象,但是不会被引用,如:栈中的本地变量、本地方法栈中的变量、方法区中的静态变量。
Spring IOC启动流程
ioc容器的启动过程分为两个步骤,第一个阶段是容器的启动阶段,第二个阶段是bean实例化阶段。
BeanDefinition 主要是用来描述 Bean,其存储了 Bean 的相关信息。
bean实例化阶段:
实例化、设置对象属性、配置依赖、会将对象实例传到 BeanPostProcessor,(方便做前置和后置处理)、注册回调接口。。。
Spring解决循环依赖
先问自己三个问题:是什么,如何出现的,怎么解决
是什么?循环依赖指的是bean和bean之间的依赖关系,循环依赖指的是两个或者多个bean相互依赖。
Spring只解决了单例Bean的 setter 注入循环依赖,对于构造器循环依赖,和 prototype模式的循环依赖是无法解决的,在创建Bean的时候就会抛出异常。
Spring容器会将每一个正在创建的Bean标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中。因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException
异常表示循环依赖。
理论依据:java基于引用类型传递,获取对象引用时,对象的属性可以延后设置。
对于单例模式,Spring整个容器的生命周期内,值存在一个对象,cache,解决循环依赖用到了三级cache。
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/** Cache of early singleton objects: bean name --> bean instance */
//实例化了,还没有初始化
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
三级,如果有动态代理的需求,可以将原始bean包装后返回。二三级是为了功能的分离?
Spring @transactional
spring定义了以@Transactional注解为切点,这样才知道其标注的方法需要被代理。
把事务行为抽象为事务管理器、事务状态、事务定义这些形态,最终将事务的开启、提交、回滚嵌入到被增强方法的前后,完成统一的事务模型管理。
注意事项
一、抛出检查异常
@Transactional
void transfer() {
try{
//...
} catch (Exception e){
LOGGER.error(e.getMessage())
}
}
方法如果是抛出检查异常,如fileNotFound,是不会回滚的,默认rollbackFor是运行时异常,可以指定rollbackFor。
@Transactional(rollbackFor = Exception.class)
二、错误try catch
捕获了异常,却没有抛出,事务不会被正确回滚。原因:Spring使用代理来管理事务,调用顺序:开启事务,执行目标方法,提交或者回滚事务,如果目标方法出现了异常,但是自己处理了,在代理类看来,就是目标方法没有抛出异常。
例如:错误情况:
@Transactional(rollbackFor = Exception.class)
public void transfer(int amount) {
try{
serviceB.sub(amount);
serviceA.add(amount);
} catch (Exception e) {
LOGGER.error("error occur");
}
}
正确做法是在catch里抛出异常或者手动告诉spring要回滚。
// 1
throw new RuntimeException(e);
// 2
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
三、只能加在public方法
spring为这个方法创建代理,添加事务,前提是public
四、调用本类方法导致传播行为失效
websocket长连接
建立WebSocket连接的过程为:
1.客户端发起HTTP请求,经过3次握手建立TCP连接,HTTP请求里存放WebSocket支持的版本号等信息。
2.服务器收到客户端握手请求后,回馈数据。
以上两个步骤完成后,HTTP握手部分完成,协议升级为WebSocket,此时服务器就不再需要客户端发起请求,再响应请求了,可以主动推送信息给客户端了。
参考: