做游戏网站有钱赚吗,长春网站建站,如何查看自己的企业邮箱,宁波小网站制作推广1、Tomcat的工作线程是基于线程池的#xff0c;线程池会重用固定的几个线程#xff0c;一旦线程重用#xff0c;那么很可能首次从ThreadLocal获取的值是之前其他用户的请求遗留的值。这时#xff0c;ThreadLocal中的用户信息就是其他用户的信息。使用类似ThreadLocal工具来…1、Tomcat的工作线程是基于线程池的线程池会重用固定的几个线程一旦线程重用那么很可能首次从ThreadLocal获取的值是之前其他用户的请求遗留的值。这时ThreadLocal中的用户信息就是其他用户的信息。使用类似ThreadLocal工具来存放一些数据时需要特别注意在代码运行完后显式地去清空设置的数据
2、大量写的场景10万次add操作CopyOnWriteArray几乎比同步的ArrayList慢一百倍在大量读的场景下100万次get操作CopyOnWriteArray又比同步的ArrayList快五倍以上
3、静态字段属于类类级别的锁才能保护而非静态字段属于类实例实例级别的锁就可以保护
4、即使我们确实有一些共享资源需要保护也要尽可能降低锁的粒度仅对必要的代码块甚至是需要保护的资源本身加锁
5、如果业务逻辑中锁的实现比较复杂的话要仔细看看加锁和释放是否配对是否有遗漏释放或重复释放的可能性并且对于分布式锁要考虑锁自动超时释放了而业务逻辑却还在进行的情况下如果别的线程或进程拿到了相同的锁可能会导致重复执行。
6、线程池默认的工作行为
不会初始化corePoolSize个线程有任务来了才创建工作线程
当核心线程满了之后不会立即扩容线程池而是把任务堆积到工作队列中
当工作队列满了后扩容线程池一直到线程个数达到maximumPoolSize为止
如果队列已满且达到了最大线程后还有任务进来按照拒绝策略处理
当线程数大于核心线程数时线程等待keepAliveTime后还是没有任务需要处理的话收缩线程到核心线程数
7、要根据任务的“轻重缓急”来指定线程池的核心参数包括线程数、回收策略和任务队列
对于执行比较慢、数量不大的IO任务或许要考虑更多的线程数而不需要太大的队列。
而对于吞吐量较大的计算型任务线程数量不宜过多可以是CPU核数或核数*2理由是线程一定调度到某个CPU进行执行如果任务本身是CPU绑定的任务那么过多的线程只会增加线程切换的开销并不能提升吞吐量但可能需要较长的队列来做缓冲。
8、JedisPool是线程安全的连接池Jedis是非线程安全的单一连接。知道了原理之后我们再使用Jedis就胸有成竹了。如果多个线程在执行操作那么既无法确保整条命令以一个原子操作写入Socket也无法确保写入后、读取前没有其他数据写到远端
9、对类似数据库连接池的重要资源进行持续检测并设置一半的使用量作为报警阈值出现预警后及时扩容。
9、连接超时参数ConnectTimeout让用户配置建连阶段的最长等待时间通常可以认为出现连接超时是网络问题或服务不在线而出现读取超时是服务处理超时
读取超时参数ReadTimeout用来控制从Socket上读取数据的最长等待时间。读取超时指的是向Socket写入数据后我们等待Socket返回数据的超时时间
通过ribbon发送get请求会有自动重试的机制可通过设置ribbon.MaxAutoRetriesNextServer0或者改为post请求。
10、spring事务Transaction生效的前提
1除非特殊配置比如使用AspectJ静态织入实现AOP否则只有定义在public方法上的Transactional才能生效
2必须通过代理过的类从外部调用目标方法才能生效
11、强烈建议你在开发时打开相关的Debug日志以方便了解Spring事务实现的细节并及时判断事务的执行情况。通过JPA访问数据库可通过logging.level.org.springframework.orm.jpaDEBUG打开
12、事务即便生效也不一定能回滚
通过AOP实现事务处理可以理解为使用try…catch…来包裹标记了Transactional注解的方法当方法出现了异常并且满足一定条件的时候在catch里面我们可以设置事务回滚没有异常则直接提交事务。
这里的“一定条件”主要包括两点。
第一只有异常传播出了标记了Transactional注解的方法事务才能回滚。或者手动回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
第二默认情况下出现RuntimeException非受检异常或Error的时候Spring才会回滚事务。可通过Transactional(rollbackFor Exception.class)检测所有异常
13、出了异常事务不一定回滚不出异常事务也不一定可以提交
14、聚簇索引、二级索引、B树、回表、成本计算
B树的特点包括
最底层的节点叫作叶子节点用来存放数据
其他上层节点叫作非叶子节点仅用来存放目录项作为索引
非叶子节点分为不同层次通过分层来降低每一层的搜索量
所有节点按照索引键大小排序构成一个双向链表加速范围查找。
15、额外创建二级索引的代价
1维护代价
2空间代价
3回表的代价
16、索引失效的情况
1索引只能匹配列前缀
2条件涉及函数操作无法走索引
3联合索引只能匹配左边的列
17、对于自定义的类型如果要实现Comparable请记得equals、hashCode、compareTo三者逻辑一致。
18、使用BigDecimal表示和计算浮点数请务必使用字符串的构造方法来初始化BigDecimal
浮点数的字符串格式化也要通过BigDecimal进行
19、BigDecimal的equals比较的是BigDecimal的value和scale如果我们希望只比较BigDecimal的value可以使用compareTo方法
20、不能直接使用Arrays.asList来转换基本类型数组
Arrays.asList返回的List不支持增删操作
对原始数组的修改会影响到我们获得的那个List
List list new ArrayList(Arrays.asList(arr));
21、使用List.subList进行切片操作居然会导致OOM
22、MySQL中sum函数没统计到任何记录时会返回null而不是0可以使用IFNULL函数把null转换为0
MySQL中count字段不统计null值COUNT(*)才是统计所有记录数量的正确方式。
MySQL中使用诸如、、这样的算数比较操作符比较NULL的结果总是NULL这种比较就显得没有任何意义需要使用IS NULL、IS NOT NULL或 ISNULL()函数来比较。
23、捕获和处理异常容易犯的错
1不在业务代码层面考虑异常处理仅在框架层面粗犷捕获和处理异常
2捕获了异常后直接生吞
3丢弃异常的原始信息
4抛出异常时不指定任何消息
24、捕获了异常打算处理的话除了通过日志正确记录异常原始信息外通常还有三种处理模式
1转换即转换新的异常抛出。对于新抛出的异常最好具有特定的分类和明确的异常消息而不是随便抛一个无关或没有任何信息的异常并最好通过cause关联老异常。
2重试即重试之前的操作。比如远程调用服务端过载超时的情况盲目重试会让问题更严重需要考虑当前情况是否适合重试。
3恢复即尝试进行降级处理或使用默认值来替代原始数据。
25、
1虽然try中的逻辑出现了异常但却被finally中的异常覆盖了
2千万别把异常定义为静态变量把异常定义为静态变量会导致异常信息固化这就和异常的栈一定是需要根据当前调用来动态获取相矛盾
3提交线程池的任务出了异常会怎么样从线程名的改变可以知道因为异常的抛出老线程退出了线程池只能重新创建一个线程。如果每个异步任务都以异常结束那么线程池可能完全起不到线程重用的作用execute提交的任务会这样submit提交的任务只有在获取执行结果的时候才会抛出异常既然是以submit方式来提交任务那么我们应该关心任务的执行结果否则应该以execute来提交任务
修复方式有2步
以execute方法提交到线程池的异步任务最好在任务内部做好异常处理
设置自定义的异常处理程序作为保底比如在声明线程池时自定义线程池的未捕获异常处理程序
26、配合使用标记和EvaluatorFilter实现日志的按标签过滤是一个不错的小技巧
27、使用Logback提供的AsyncAppender即可实现异步的日志记录
28、在进行文件IO处理的时候使用合适的缓冲区可以明显提高性能
29、默认情况下在反序列化的时候Jackson框架只会调用无参构造方法创建对象
30、定义的static的SimpleDateFormat可能会出现线程安全问题比较好的解决方式是通过ThreadLocal来存放SimpleDateFormat
private static ThreadLocalSimpleDateFormat threadSafeSimpleDateFormat ThreadLocal.withInitial(() - new SimpleDateFormat(yyyy-MM-dd HH:mm:ss));