省建设干部培训中心网站上海网站的建设

张小明 2026/1/2 15:35:13
省建设干部培训中心网站,上海网站的建设,企业管理培训课程内容,网站建设与维护实训报告总结#xff1a;Java届很难得有读百十行代码就能增加修炼的机会#xff0c;这里有一个。通常#xff0c;我在看书的时候一般不写代码#xff0c;因为我的脑袋被设定成单线程的#xff0c;一旦同时喂给它不同的信息#xff0c;它就无法处理。但多线程对电脑来说就是小菜一…总结Java届很难得有读百十行代码就能增加修炼的机会这里有一个。通常我在看书的时候一般不写代码因为我的脑袋被设定成单线程的一旦同时喂给它不同的信息它就无法处理。但多线程对电脑来说就是小菜一碟它可以同时做很多事看起来匪夷所思。好希望把自己的大脑皮层移植到这些牛x的设备上。用人脑思考电脑正在思考的问题这本身就是一种折磨。但平常的工作和面试中又不得不面对这样的场景所以多线程就成了编程路上一块难啃的骨头。HikariCP是SpringBoot默认的数据库连接池它毫不谦虚的的起了一个叫做光的名字这让国产Druid很没面子。还是言归正传看一下Hikari中的ConcurrentBag吧。核心数据结构多线程代码一个让人比较头疼的问题就是每个API我都懂但就是不会用。很多对concurrent包倒背如流的同学在面对现实的问题时到最后依然不得不被迫加上Lock或者synchronized。ConcurrentBag是一个Lock free的数据结构主要用作数据库连接的存储可以说整个HikariCP的核心就是它。删掉乱七八糟的注释和异常处理可以说关键的代码也就百十来行但里面的道道却非常的多。ConcurrentBag速度很快要达到这个目标就需要一定的核心数据结构支持。private final CopyOnWriteArrayListT sharedList; private final ThreadLocalListObject threadList; private final AtomicInteger waiters; private final SynchronousQueueT handoffQueue;sharedList用来缓存所有的连接是一个CopyOnWriteArrayList结构。threadList用来缓存某个线程所使用的所有连接相当于快速引用是一个ThreadLocal类型的ArrayList。waiters当前正在获取连接的等待者数量。AtomicInteger就是一个自增对象。当waiters的数量大于0时候意味着有线程正在获取资源。handoffQueue0容量的快速传递队列SynchronousQueue类型的队列非常有用。ConcurrentBag里面的元素为了能够无锁化操作需要使用一些变量来标识现在处于的状态。抽象的接口如下public interface IConcurrentBagEntry{ int STATE_NOT_IN_USE 0; int STATE_IN_USE 1; int STATE_REMOVED -1; int STATE_RESERVED -2; boolean compareAndSet(int expectState, int newState); void setState(int newState); int getState(); }有了这些数据结构的支持我们的ConcurrentBag就可以实现它光的宣称了。获取连接连接的获取是borrow方法还可以传入一个timeout作为超时控制。public T borrow(long timeout, final TimeUnit timeUnit) throws InterruptedException首先如果某个线程执行非常快使用了比较多的连接就可以使用ThreadLocal的方式快速获取连接对象而不用跑到大池子里面去获取。代码如下。// Try the thread-local list first final var list threadList.get(); for (int i list.size() - 1; i 0; i--) { final var entry list.remove(i); final T bagEntry weakThreadLocals ? ((WeakReferenceT) entry).get() : (T) entry; if (bagEntry ! null bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) { return bagEntry; } }我们都知道包括ArrayList和HashMap一些基础的结构都是Fail Fast的如果你在遍历的时候删掉一些数据有可能会引起问题。幸运的是由于我们的List是从ThreadLocal获取的它首先就避免了线程安全的问题。接下来就是遍历。这段代码采用的是尾遍历头遍历会出现错误用于快速的从列表中找到一个可以复用的对象然后使用CAS来把状态置为使用中。但如果对象正在被使用则直接删除它。在ConcurrentBag里每个ThreadLocal最多缓存50个连接对象引用。当ThreadLocal里找不到可复用的对象它就会到大池子里去拿。也就是下面这段代码。// Otherwise, scan the shared list ... then poll the handoff queue final int waiting waiters.incrementAndGet(); try { for (T bagEntry : sharedList) { if (bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) { // If we may have stolen another waiters connection, request another bag add. if (waiting 1) { listener.addBagItem(waiting - 1); } return bagEntry; } } listener.addBagItem(waiting); // 还拿不到就需要等待别人释放了 timeout timeUnit.toNanos(timeout); do { final var start currentTime(); final T bagEntry handoffQueue.poll(timeout, NANOSECONDS); if (bagEntry null || bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) { return bagEntry; } timeout - elapsedNanos(start); } while (timeout 10_000); return null; } finally { waiters.decrementAndGet(); }首先要注意这段代码可能是由不同的线程执行的所以必须要考虑线程安全问题。由于shardList是线程安全的CopyOnWriteArrayList适合读多写少的场景我们可以直接进行遍历。这段代码的目的是一样的需要从sharedList找到一个空闲的连接对象。这里把自增的waiting变量传递到外面的代码进行处理主要是由于想要根据waiting的大小来确定是否创建新的对象。如果无法从池子里获取连接则需要等待别的线程释放一些资源。创建对象的过程是异步的要想获取它还需要依赖一段循环代码。while循环代码是纳秒精度会尝试从handoffQueue里获取。最终会调用SynchronousQueue的transfer方法。归还连接有借就有还当某个连接使用完毕它将被归还到池子中。public void requite(final T bagEntry) { bagEntry.setState(STATE_NOT_IN_USE); for (var i 0; waiters.get() 0; i) { if (bagEntry.getState() ! STATE_NOT_IN_USE || handoffQueue.offer(bagEntry)) { return; } else if ((i 0xff) 0xff) { parkNanos(MICROSECONDS.toNanos(10)); } else { Thread.yield(); } } final var threadLocalList threadList.get(); if (threadLocalList.size() 50) { threadLocalList.add(weakThreadLocals ? new WeakReference(bagEntry) : bagEntry); } }首先把这个对象置为可用状态。然后代码会进入一个循环等待使用方把这个连接接手过去。当连接处于STATE_NOT_IN_USE状态或者队列中的数据被取走了那么就可以直接返回了。由于waiters.get()是实时获取的有可能长时间一直大于0这样代码就会变成死循环浪费CPU。代码会尝试不同层次的睡眠一个是每隔255个waiter睡10ns一个是使用yield让出cpu时间片。如果归还连接的时候并没有被其他线程获取到那么最后我们会把归还的连接放入到相对应的ThreadLocal里因为对一个连接来说借和还通常是一个线程。知识点看起来平平无奇的几行代码为什么搞懂了就能Hold住大部分的并发编程场景呢主要还是这里面的知识点太多。下面我简单罗列一下你可以逐个攻破。使用ThreadLocal来缓存本地资源引用使用线程封闭的资源来减少锁的冲突采用读多写少的线程安全的CopyOnWriteArrayList来缓存所有对象几乎不影响读取效率使用基于CAS的AtomicInteger来计算等待者的数量无锁操作使得计算更加快速0容量的交换队列SynchronousQueue使得对象传递更加迅速采用compareAndSet的CAS原语来控制状态的变更安全且效率高。很多核心代码都是这么设计的在循环中使用park、yield等方法避免死循环占用大量CPU需要了解并发数据结构中的offer、poll、peek、put、take、add、remove方法的区别并灵活应用CAS在设置状态时采用了volatile关键字修饰对于volatile的使用也是一个常见的优化点需要了解WeakReference弱引用在垃圾回收时候的表现麻雀虽小五脏俱全。如果你想要你的多线程编程能力更上一层楼读一读这个短小精悍的ConcurrentBag吧。当你掌握了它多线程的那些东西不过是小菜一碟。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

ktv网站建设方案wordpress评分管理插件

终极编程字体优化指南:如何在深色模式下大幅提升代码显示效果 【免费下载链接】Hasklig Hasklig - a code font with monospaced ligatures 项目地址: https://gitcode.com/gh_mirrors/ha/Hasklig 在当今编程环境中,深色模式已成为开发者们的首选…

张小明 2025/12/29 3:29:48 网站建设

网站维护客户开发公司移交给物业资料说明

Wan2.2-T2V-A14B 如何实现电影级手持摄影风格? 在影视制作中,一个简单的镜头晃动往往能瞬间拉近观众与画面的距离——那种轻微的、不规则的抖动感,像是有人真的举着摄像机冲进了现场。它不属于完美构图,却承载着真实的情绪张力。而…

张小明 2025/12/29 3:29:15 网站建设

沈阳网站制作费用怎么在百度上推广自己的产品

.NET 中的 Web 流、序列化与隔离存储技术详解 1. Web 流的使用 在开发可扩展的应用程序时,我们可以将异步文件读取和异步网络读取结合起来,以处理多个客户端的请求。而 Web 流则提供了一种从互联网上的任何网页读取数据的便捷方式。 1.1 WebRequest 和 WebResponse WebRe…

张小明 2025/12/29 3:28:41 网站建设

网站建设用户画像例子广东官网网站建设公司

Dify平台在股票行情评论自动生成中的时效性挑战应对 金融市场从不等人。当某只热门股票突然放量涨停,投资者的手机几乎在同一时间弹出各类财经推送——而背后,往往是分析师争分夺秒撰写、审核、发布的成果。但在信息爆炸的时代,人工操作的速度…

张小明 2025/12/29 3:28:08 网站建设

上海高端定制网站公司宿迁房产网租房信息

第一章:Open-AutoGLM核心技术揭秘架构设计理念 Open-AutoGLM 采用模块化解耦设计,将自然语言理解、任务规划、代码生成与执行反馈四大核心能力分离,通过统一的中间表示层(Intermediate Representation, IR)进行通信。该…

张小明 2025/12/29 3:22:38 网站建设

js做网站登录界面网站注册凡科

目录具体实现截图项目介绍论文大纲核心代码部分展示可定制开发之亮点部门介绍结论源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作具体实现截图 本系统(程序源码数据库调试部署讲解)同时还支持Python(flask,django)、…

张小明 2025/12/30 11:52:42 网站建设