如何设计一个线程安全类
前言招行卡中心二面问到的面试题,当时答得磕磕绊绊,复盘一下。
问题分析一个线程安全类的理想效果是,调用者在调用该类时,无需考虑类中变量是否线程共享、操作是否线程安全,不需要进行额外的同步操作。
这就意味着该类在设计时,需要考虑在多线程调用的情况下,哪些变量、哪些对变量的操作会受到影响,把这些元素集合起来,进行同步封装,使得调用者线程可以直接使用,尽可能地减少在多线程环境下产生意料之外结果的可能性。
设计思路封装共享变量找出共享、可变的字段是否共享?
访问权限:private、protected、public、default
暴露了可供外界读取的接口:get方法
是否可变?
基本数据类型还是引用数据类型?
引用数据类型的可变性体现在两方面
地址改变了;
地址指向的变量内容改变了
如何控制一个变量不可变?
使用final关键字
用锁来保护访问找到所有共享、可变的字段之后,需要对所有暴露在外的接口进行同步处理。
注意是所有!并不是只有写操作需要同步,读操作如果没有进行锁定,在多线程环境下有可能读到错误的值从而产生意料之外的结果。
一般,使用对象锁保证多线程对共享可变字段的 ...
单例模式
前言很简单的单例模式实现,笔试的时候写错了💦💦,复习一下。
分类饿汉模式类创建时就初始化唯一实例
优点:简单、线程安全
缺点:可能耗费资源
12345678910public class HungrySingleton { // 定义并初始化唯一实例 private static final HungrySingleton instance = new HungrySingleton(); // 私有化构造函数 private HungrySingleton() {} // 返回示例的静态方法 public static HungrySingleton getUniqueInstance() { return instance; }}
懒汉模式第一次被调用时才创建实例
优点:节省资源
缺点:线程不安全
12345678910111213public class LazySingleton { // 定义唯一实例,但是不初始化 priva ...
文件上传方案
前言传统上,上传文件时,前端先把文件发给后端,后端接收到文件后再落盘或上传至OOS。
随着云服务的发展,前端可以直接上传文件至OOS。但是前端作为第三方向OOS上传文件需要凭证(例如token和秘钥),直接将凭证放入请求体发送上传请求显然是极度危险的。
因此,这里总结一下如何安全地实现前端直传OOS。
传统场景场景说明首先复习一下最传统的文件上传场景,即前端发送文件至后端,后端接收文件后上传至OOS或落盘。
示例代码POST请求
Controller获取post请求体中的参数,包括文件和其他表单数据。
1234567@PostMapping("/upload")public void upload(@RequestParam("file") MultipartFile file, @RequestParam("uploader") String uploader, @Requ ...
LinkedList与Stack常用API
前言LinkedList的底层是双向链表,实现了Queue接口,可以作为队列、栈来使用,有着很多与双向链表操作相关的API,且有一部分API功能相同,又容易与Stack的部分API混淆。所以在这里记下其作为双端队列使用时常用的API,刷题的时候能第一时间想起来正确的接口去使用即可。
示例简单来说就是:
LinkedList:add、peek、remove
Stack:push、peek、pop
LinkedList1234567891011121314151617public static void testQueue() { LinkedList<Integer> q = new LinkedList<>(); // 添加到队尾 -> 1 q.add(1); // 添加到队首 -> 2 1 q.addFirst(2); // 添加到队尾 -> 2 1 3 q.add(3); // 取队首元素 -> [2] 1 3 ...
JSR303
简介JSR是Java Specification Requests的缩写,意思是Java 规范提案。
JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,为Bean验证定义了元数据模型和API。
默认的元数据模型是通过Annotations来描述的,但是也可以使用XML来重载或者扩展。
常用校验注解
Bean Validation 中内置的 constraint
Constraint
详细信息
@Null
被注释的元素必须为 null
@NotNull
被注释的元素必须不为 null
@AssertTrue
被注释的元素必须为 true
@AssertFalse
被注释的元素必须为 false
@Min(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)
被注释的元素必须是一个 ...
日志初见
前言日志可以用来帮助开发人员进行故障排查、性能监控、安全监控以及业务流程跟踪等。相比于最原始的System.out.println()输出,日志框架可以对日志程序信息进行分级分类展示,具有更好的可读性,同时可以方便地对日志信息进行控制与存储,十分便利!这里主要记录如何使用Spring Boot默认支持的Logback进行日志的配置。如果有误,还望指出~
在哪里打印日志打印行为一般发生在Service层。
Service层是业务逻辑的主要实现地点,包含了应用程序的核心逻辑,在Service层打印日志可以更加紧贴业务逻辑。
此外,Service层通常包含可重用的业务逻辑,这些逻辑可能被多个Controller调用。通过在Service层记录日志,可以确保在每个调用点都有相同的日志记录,而不需要在每个Controller中重复编写日志记录代码。
如何打印在需要打印日志信息的Java类中引入Logger实例,并调用相关方法即可。
123456789101112131415@RestControllerpublic class LoggingController { Logger ...
Windows 11下安装RabbitMQ
前言要在本机跑一个项目,会用到这个东西,安装配置一下,细致的东西等之后在写,这篇先简单做个安装的记录。
安装下载
官网下载地址:Installing on Windows | RabbitMQ
安装安装Erlang官网下载:Downloads - Erlang/OTP,下载完成之后一路Next下来即可,安装路径不要有中文和空格。
安装完成之后设置一下Erlang的环境变量。
检查一下安装成功:
安装RabbitMQ运行rabbitmq-server-3.13.1_2.exe,也是一路Next,安装完成后默认启动服务。
安装RabbitMQ-Plugins进入D:\Environments\RabbitMQ-3.13\rabbitmq_server-3.13.1\sbin运行:
1rabbitmq-plugins enable rabbitmq_management
验证浏览器进入:RabbitMQ Management,用户名和密码都是guest。
成了,项目也跑起来了嘿嘿。
颜文字存档
前言存着用来写博客卖萌用嘻嘻(*^3^)
可爱小脸蛋૮◍⁰ᯅ⁰◍ა ᖰ⌯’▾’⌯ᖳ ʕ.•᷅ࡇ•᷄.ʔ ໒𖦹ࡇ𖦹 ͛১
૮ ˃̣̣̥⌓˂̣̣̥ა ฅ˙Ⱉ˙ฅ ۶•͈⚇•͈ა ۶•͈⚇•͈♡ (˶╹ꇴ╹˶)
૮₍ꐦ -᷅ ⤙ -᷄ ₎ა ૮꒰˶ฅ́˘ฅ̀˶꒱ა ૮꒰ ˶• ༝ •˶꒱ა ˃̣̣̣̣̣̣︿˂̣̣̣̣̣̣
𖦹.𖦹 ᖰ ᵕ༚ᵕ ᖳ ᖰ ˙ỏ˙ ᖳ ʚ •͈˽•͈ ིྀɞ ⋆͛♥︎⋆͛
·̩͙꒰ঌ✞໒꒱· ゚ ₊⁺♡̶♡̶♡̶♡̶₊⁺ ‧ ·̩͙(:̲̅:̲̅:̲̅[̲̅:♡:]̲̅:̲̅:̲̅:̲̅)
*ଘ(♡̷⸝⸝•༝•⸝⸝)੭̸੭̸✩ ꒰ঌ₊⁺♡̶₊⁺໒꒱ °ʚ✞ɞ° ❛‿˂̵✧
˗ˋˏ♡ˎˊ˗ ˗ˏˋ♥︎︎ˎˊ˗ ₍ᐢ⸝⸝› ̫‹⸝⸝ᐢ₎ •᷄ᯅ•᷅ •᷄ࡇ•᷅
૮ ///▽/// ა ฅ⁽͑ ˚̀ ˙̭ ˚ ⁾̉ฅ ...
软件定义网络初见
前言为毕设做的一个小调研,大部分还是整理的其他博文的内容,有错误还望指出!
定义软件定义网络(Software-Defined Networking,SDN)的官方定义可以追溯到2011年由ONF(Open Networking Foundation)发布的文档。其中,SDN被定义为一种网络架构,通过对网络控制面和数据面进行解耦,实现了网络控制的集中和程序化。
出现背景传统IP网络的分布式架构虽然具有强大的生存能力,但是不允许集中控制。不允许集中控制意味着当需要对一个网络中的某些配置进行修改,或需要为网络增加某种新的服务时,可能需要考虑调整网络中每个设备的配置项和逻辑控制。举个例子:
假设一个公司有一个传统的企业网络,由多个路由器和交换机组成。现在公司需要增加一个新的服务,要求特定类型的流量通过一条特定的路径,而不是根据传统的路由协议选择最佳路径。在传统网络中,管理员需要手动配置每个设备,以确保特定类型的流量按照要求的路径进行转发。这样的配置过程复杂繁琐,容易出错,并且难以保证一致性。而在SDN中,管理员可以通过集中的控制器来动态配置网络,只需在控制器上进行一次配置即可实现整个网络的 ...
快速幂
问题引入如何快速求 a^n^
分析依照 a^n^的定义只需将n个a相乘即可,这样的时间复杂度为o(n),快速幂算法就是为了加速n个a相乘的过程。
举例来说,当n为2的幂时,比如n = 64,那么只需要乘6次就可到得到结果了。
当n不为2的幂,比如n = 105时,可以将n拆成2的幂的和,即n = 1 + 8 + 32 + 64,即a^105^ = a^1^ * a^8^ * a^32^ * a^64^。
代码伪代码对n每次右移1位,当右移k次时,此时n的末尾数字就是n原来第k位上的数字,为1代表2^k^参与到a^n^的计算中,为0则代表不参与。
12345678function BinExp(a, n) r = 1 while n != 0 if n mod 2 == 1 r = r × a a = a × a n >> 1 return r
参考链接
【快速幂都能做什么?小小的算法也有大大的梦想】 https://www.bilibili.com ...