决战圣地玛丽乔亚Day32---JUC并发包的核心内容
copyOnWrite容器用途
写时复制机制,在修改操作时,复制一个副本,修改副本,再修改完后再替换回去。避免了高并发期间的竞争。
使用场景:
对于一些读多写少的数据,写时复制的做法就很不错,例如配置、黑名单、物流地址等变化非常少的数据,这是一种无锁的实现,可以帮我们实现程序更高的并发
CopyOnWriteArrayList并发安全且性能比Vector好。Vector是curd方法都加了synchronized来保证同步,但是每个方法执行的时候都要去获得锁,性能就会大大下降,而COW只是在增删改上加锁,读不加锁,在读方面的性能就好于Vector。
注意两个问题
1.内存问题。
多个变量指向同一内存地址,如果某一变量修改数据,会形成副本,副本会占用空间。
如果CopyOnWriteArrayList经常要增删改里面的数据,并且对象比较大,频繁地写会消耗内存,从而引发Java的GC问题,这个时候,我们应该考虑其他容器,例如ConcurrentHashMap
当数据修改完成后,原内存地址会变得无用,导致内存碎片的产生。
2.数据一致性问题。
只能保证最终一致性,不能保证实时一致性。
Unsafe类的用途
在Java编程语言中,Unsafe
类提供了一种非常底层的操作方式,可以用于执行一些危险或不安全的操作,包括:
-
直接操作内存:
Unsafe
类提供了一些方法来读取、写入和操作内存,例如putInt
、getInt
、allocateMemory
等。这些方法可以用于优化某些性能关键的算法,但同时也可能导致内存访问错误,甚至是崩溃。 -
修改对象字段:
Unsafe
类可以绕过Java对象的访问限制,直接修改对象的字段。这在一些极端情况下可能是必要的,但也会破坏对象的封装性,导致对象状态不可预测。 -
创建实例:
Unsafe
类提供了一些方法来创建类的实例,包括绕过构造函数直接分配内存和初始化字段。这可以用于实现一些高级技术,例如对象池和反序列化,但也可能导致对象状态不一致和内存泄漏。
需要注意的是,由于Unsafe
类的操作非常底层,因此在使用时需要格外小心,避免出现潜在的安全隐患和错误。建议只有在真正需要时才使用Unsafe
类,否则应该优先选择更安全、更易于维护的解决方案。
Callable和Runnable的区别?
示例:
1 2 3 4 5 6 7 8 | / Runnable 示例 Runnable runnable = new Runnable() { public void run() { // 执行一些操作 } }; Thread thread = new Thread(runnable); thread.start();<br> |
1 2 3 4 5 6 7 8 9 10 | // Callable 示例 Callable<String> callable = new Callable<String>() { public String call() throws Exception { // 执行一些操作 return "result" ; } }; ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<String> future = executorService.submit(callable); String result = future.get(); // 等待操作完成并获取结果 |
返回值:Runnable的run方法没有返回值,callable可以返回一个结果。
异常处理:run不能抛出异常 ,call可以抛出异常
使用方式:是否需要返回值来决定场景。
如果需要用run来执行一个可能会异常的操作,在run里面需要手动写一下异常处理。
CompleteFuture的使用?
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!