详解Java信号量-Semaphore

2024-01-21

第1章:引言

大家好,我是小黑。今天,咱们一起来深入探讨一下Semaphore。在Java中,正确地管理并发是一件既挑战又有趣的事情。当谈到并发控制,大家可能首先想到的是synchronized关键字或者是ReentrantLock。但其实,Java还提供了一个非常强大的工具,就是Semaphore。

Semaphore,直译过来就是“信号量”。在日常生活中,信号灯控制着车辆的通行,防止交通混乱,这其实和Semaphore在程序中的作用颇为相似。Semaphore主要用于控制同时访问特定资源的线程数量,它通过协调各个线程,保证合理的使用公共资源。比方说如果有一家餐馆只允许固定数量的顾客同时用餐,这就是Semaphore的经典应用场景。

第2章:Semaphore的基本概念

让我们先来了解一下Semaphore的基本概念。在Java中,Semaphore是位于 java.util.concurrent 包下的一个类。它的核心就是维护了一个许可集。简单来说,就是有一定数量的许可,线程需要先获取到许可,才能执行,执行完毕后再释放许可。

那么,这个许可是什么呢?其实,你可以把它想象成是对资源的访问权。比如,有5个许可,就意味着最多允许5个线程同时执行。线程可以通过 acquire() 方法来获取许可,如果没有可用的许可,该线程就会阻塞,直到有许可可用。

让我们看个简单的例子。假设咱们有一个限制了最多同时3个线程执行的Semaphore:


  

java

复制代码

import java.util.concurrent.Semaphore; public class SemaphoreExample { // 创建一个Semaphore实例,许可数量为3 private static final Semaphore semaphore = new Semaphore(3); public static void main(String[] args) { // 创建并启动三个线程 for (int i = 1; i <= 3; i++) { new Thread(new Task(semaphore), "线程" + i).start(); } } static class Task implements Runnable { private final Semaphore semaphore; public Task(Semaphore semaphore) { this.semaphore = semaphore; } @Override public void run() { try { // 请求许可 semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " 获取许可,正在执行"); Thread.sleep(1000); // 模拟任务执行 System.out.println(Thread.currentThread().getName() + " 执行完毕,释放许可"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { // 释放许可 semaphore.release(); } } } }

在这个例子中,咱们创建了一个Semaphore实例,设置最大许可数为3。这意味着,最多只能有3个线程同时运行Task中的代码。每个线程在开始执行前,都会尝试通过 acquire() 方法获取一个许可。

第3章:Semaphore的核心原理

现在,咱们深入一下Semaphore的核心原理。理解这个原理对于掌握Semaphore的高效使用至关重要。在Java中,Semaphore不仅仅是个计数器,它背后的原理和实现逻辑比看起来要复杂得多。

Semaphore的核心是基于AQS(AbstractQueuedSynchronizer)这个框架。AQS是Java并发包中的一个非常重要的组件,它用来构建锁或者其他同步器。简单来说,AQS提供了一种机制,可以让线程在访问某个资源前进入等待状态,并在资源可用时被唤醒。这正是Semaphore的基础。

Semaphore维护了一个许可集,这个集合的大小在初始化时设定。每次调用 acquire() 方法,Semaphore会试图从这个集合中取出一个许可。如果没有可用的许可,线程就会被阻塞,直到有其他线程释放一个许可。相反, release() 方法会增加许可的数量,并有可能唤醒等待的线程。

让小黑通过一段代码来更好地说明这个原理:


  

java

复制代码

import java.util.concurrent.Semaphore; public class SemaphoreDeepDive { public static void main(String[] args) { // 初始化一个只有2个许可的Semaphore Semaphore semaphore = new Semaphore(2); Runnable task = () -> { try { // 尝试获取许可 semaphore.acquire(); System.out.println("线程 " + Thread.currentThread().getName() + " 获取了许可"); // 模拟任务执行 Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { // 释放许可 semaphore.release(); System.out.println("线程 " + Thread.currentThread().getName() + " 释放了许可"); } }; // 创建并启动3个线程 for (int i = 0; i < 3; i++) { new Thread(task).start(); } } }

在这个例子中,Semaphore被初始化为只有两个许可。当三个线程尝试运行时,只有两个能够同时执行。第三个线程必须等待,直到一个许可被释放。这就是Semaphore控制并发的机制。

第4章:使用Semaphore的场景

咱们来聊聊Semaphore在实际编程中的应用场景。理解了Semaphore的基础和原理后,咱们现在可以探索它在实际场景中的具体使用。Semaphore非常灵活,可以用于多种场合,特别是在控制资源访问的并发环境中。

场景一:资源池

想象一下,小黑有一个数据库连接池,这个池子里只有几个数据库连接。如果所有的连接都被占用了,其他需要数据库连接的线程就得等待。这就是Semaphore的经典应用场景。通过限制可用的连接数量,Semaphore确保了不会有太多的线程同时访问数据库。

场景二:限流

在Web服务中,咱们可能想要限制某个服务的并发请求数量,以防止服务器过载。Semaphore可以很容易地实现这个功能。设置一个固定数量的许可,就可以限制同时处理的请求数量。

代码示例

让小黑用代码展示一下这些场景。首先,是一个简单的数据库连接池的示例:


  

java

复制代码

import java.util.concurrent.Semaphore; public class DatabaseConnectionPool { private final Semaphore semaphore; private final String[] connectionPool; private final boolean[] used; public DatabaseConnectionPool(int poolSize) { semaphore = new Semaphore(poolSize); connectionPool = new String[poolSize]; used = new boolean[poolSize]; for (int i = 0; i < poolSize; i++) { connectionPool[i] = "连接 " + (i + 1); } } public String getConnection() throws InterruptedException { semaphore.acquire(); return getNextAvailableConnection(); } public void releaseConnection(String connection) { if (markAsUnused(connection)) { semaphore.release(); } } private synchronized String getNextAvailableConnection() { for (int i = 0; i < connectionPool.length; i++) { if (!used[i]) { used[i] = true; return connectionPool[i]; } } return null; // 不应该发生,semaphore保证了有可用连接 } private synchronized boolean markAsUnused(String connection) { for (int i = 0; i < connectionPool.length; i++) { if (connection.equals(connectionPool[i])) { used[i] = false; return true; } } return false; } }

这个代码演示了如何使用Semaphore来控制对有限数量资源(数据库连接)的访问。每个连接在使用前需要获得一个许可,使用完后释放许可。

第5章:Semaphore的高级特性

公平性与非公平性

Semaphore有两种模式:公平模式和非公平模式。公平模式下,线程获得许可的顺序与它们请求许可的顺序一致,就像排队一样。而非公平模式则没有这种保证,线程可以“插队”,这可能会导致某些线程等待时间过长。

在Java中,创建Semaphore时可以指定是公平模式还是非公平模式。默认情况下,Semaphore是非公平的。公平模式通常会有更高的性能开销,因为它需要维护一个更加复杂的内部结构来保证顺序。

可中断操作

在Semaphore中,等待许可的操作可以是可中断的。这意味着如果一个线程在等待一个许可时被中断,它可以选择退出等待。这在处理某些需要响应中断的场景时非常有用。

代码示例

让小黑给你演示一下这两个特性的代码实例:


  

java

复制代码

import java.util.concurrent.Semaphore; public class SemaphoreAdvancedFeatures { public static void main(String[] args) throws InterruptedException { // 创建一个公平模式的Semaphore Semaphore fairSemaphore = new Semaphore(1, true); // 创建并启动两个线程 Thread t1 = new Thread(new Worker(fairSemaphore), "线程1"); Thread t2 = new Thread(new Worker(fairSemaphore), "线程2"); t1.start(); t2.start(); // 演示可中断操作 Thread interruptibleThread = new Thread(() -> { try { fairSemaphore.acquire(); System.out.println(Thread.currentThread().getName() + " 获取了许可"); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() + " 被中断"); } }); interruptibleThread.start(); Thread.sleep(1000); // 等待一会 interruptibleThread.interrupt(); // 中断线程 } static class Worker implements Runnable { private final Semaphore semaphore; Worker(Semaphore semaphore) { this.semaphore = semaphore; } @Override public void run() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " 获取了许可"); Thread.sleep(2000); // 模拟工作 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { semaphore.release(); System.out.println(Thread.currentThread().getName() + " 释放了许可"); } } } }

在这个代码中,小黑创建了一个公平模式的Semaphore,并演示了两个线程按顺序获取许可的情况。同时,还展示了一个线程在尝试获取许可时如何被中断。

第6章:Semaphore的问题与解决方案

问题一:资源耗尽

最常见的问题之一是资源耗尽。当所有许可都被占用,并且持有许可的线程因某种原因无法释放许可时,就会出现资源耗尽的情况。这可能会导致其他线程永久等待,从而造成死锁。

解决方案 :确保在使用资源后总是释放许可。可以使用 try-finally 块来确保即使在发生异常时也能释放许可。

问题二:公平性问题

如前所述,Semaphore可以是公平的或非公平的。在非公平模式下,有可能导致某些线程饥饿,即永远得不到执行的机会。

解决方案 :如果需要保证每个线程都有机会执行,可以考虑使用公平模式的Semaphore。

问题三:性能问题

在高并发场景中,Semaphore可能成为性能瓶颈。由于线程频繁地获取和释放许可,可能会导致过多的上下文切换和竞争。

解决方案 :适当调整许可的数量,或者寻找其他更适合高并发场景的并发工具。

代码示例

让小黑通过代码来展示如何妥善处理这些问题:


  

java

复制代码

import java.util.concurrent.Semaphore; public class SemaphoreProblemSolving { private static final Semaphore semaphore = new Semaphore(1); public static void main(String[] args) { Thread thread1 = new Thread(SemaphoreProblemSolving::safeMethod, "线程1"); Thread thread2 = new Thread(SemaphoreProblemSolving::safeMethod, "线程2"); thread1.start(); thread2.start(); } private static void safeMethod() { try { semaphore.acquire(); try { // 执行关键区域代码 System.out.println(Thread.currentThread().getName() + " 在执行"); Thread.sleep(1000); } finally { semaphore.release(); // 确保总是释放许可 } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }

在这段代码中,小黑展示了如何使用 try-finally 块来确保无论如何都会释放Semaphore的许可。这种方式可以减少由于异常导致的资源耗尽问题。

第7章:与其他并发工具的结合使用

结合CountDownLatch

CountDownLatch 是一种同步帮助,它允许一个或多个线程等待其他线程完成一系列操作。在某些场景中,咱们可能需要先用Semaphore控制资源访问,然后使用 CountDownLatch 来同步多个线程的进度。

结合CyclicBarrier

CyclicBarrier CountDownLatch 类似,但它允许一组线程相互等待,达到一个共同的障碍点再继续执行。这在需要多个线程在某个点同步执行的场景中非常有用。结合Semaphore,可以在达到共同点之前控制线程对资源的访问。

代码示例

让小黑给咱们展示一个结合使用Semaphore和CountDownLatch的例子:


  

java

复制代码

import java.util.concurrent.CountDownLatch; import java.util.concurrent.Semaphore; public class CombinedSemaphoreCountDownLatch { private static final int THREAD_COUNT = 5; private static final Semaphore semaphore = new Semaphore(2); private static final CountDownLatch latch = new CountDownLatch(THREAD_COUNT); public static void main(String[] args) throws InterruptedException { for (int i = 0; i < THREAD_COUNT; i++) { new Thread(new Worker(i, semaphore, latch)).start(); } latch.await(); // 等待所有线程完成 System.out.println("所有线程执行完毕"); } static class Worker implements Runnable { private final int workerNumber; private final Semaphore semaphore; private final CountDownLatch latch; Worker(int workerNumber, Semaphore semaphore, CountDownLatch latch) { this.workerNumber = workerNumber; this.semaphore = semaphore; this.latch = latch; } @Override public void run() { try { semaphore.acquire(); System.out.println("工人 " + workerNumber + " 正在工作"); Thread.sleep(1000); // 模拟工作 semaphore.release(); latch.countDown(); // 完成工作,计数减一 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } }

在这个例子中,小黑创建了一个包含5个线程的场景。使用Semaphore来控制同时工作的线程数量,同时使用CountDownLatch来确保所有线程都完成工作后主线程才继续执行。

第8章:总结

  • 基本概念 :Semaphore是一种基于计数的同步工具,用于控制同时访问特定资源的线程数量。
  • 原理理解 :Semaphore的实现依赖于AQS(AbstractQueuedSynchronizer),提供了一种机制来管理和控制线程的访问。
  • 实际应用 :从资源池管理到限流控制,Semaphore在多种场景中都非常有用。
  • 高级特性 :包括公平性和非公平性的选择,以及对线程中断的响应。
  • 问题解决 :面对资源耗尽和性能问题,咱们学习了如何妥善处理Semaphore带来的挑战。
  • 与其他工具结合 :Semaphore能与CountDownLatch、CyclicBarrier等并发工具结合使用,解决更复杂的并发问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详解Java信号量-Semaphore 的相关文章

  • Buildozer Numpy RuntimeError:工具链损坏:无法链接简单的 C 程序

    用 Python 编写我的第一个 Android 应用程序并使用 Buildozer 对其进行打包 因为稍后在项目中需要使用numpy 所以我尝试打包以下测试代码 import numpy import kivy kivy require
  • 改造添加带有令牌和 ID 的标头

    我在获取经过身份验证的用户时遇到问题 在此之前我得到了令牌和用户 ID 现在我需要使用访问令牌和 ID 从服务器获取用户 我有标题格式 https i stack imgur com OQ87Y png 现在我尝试使用拦截器添加带有用户令牌
  • 带有redirect_uri的social-auth-app-django Facebook后端状态

    我知道我的问题听起来像是重复的 但我到处寻找但没有找到任何解决方案 我正在努力为我的 django web 应用程序实现社交登录 到目前为止 谷歌 推特和雅虎登录均按预期工作 但facebook总是给出以下错误 URL 被阻止 此重定向失败
  • Django - 该进程无法访问该文件,因为该文件正在被另一个进程使用

    我正在尝试在 Windows 10 上运行 Django 我是 Django 的新手 我正在使用 Compressor Toolkit 我的问题是 我可以运行 manage py 但本地主机说 base html 第 9 行出错该进程无法访
  • 飞碟中的外部 CSS

    我想知道如何在 Flying Saucer 中包含外部 CSS 在此之前THB我检查了所有可用的链接StackOverflow但它们没有帮助 这就是为什么我自己做这个的原因 TestCSS xhtml重命名版本TestCSS html 所以
  • 在单独的模块中使用 Spring AOP 方面

    我在一个 Maven 项目模块中有一个方面 com x NiceAspect 在一个单独的 Maven 模块中有一个类 com x NiceClass 这些模块具有相同的 POM 父级 共同创建一个项目 我想要实现的目标是拥有一个通用的方面
  • 如何避免在matplotlib中调用latex(输出到pgf)

    我使用 matplotlib 及其 pgf 后端来生成包含在 LaTeX 投影仪文档中的绘图 当我使用未定义的乳胶命令时 我遇到了麻烦 但对于我的应用程序 我不需要 matplotlib 来使用 Latex 生成标签或注释 我只想要正确的
  • 将 Selenium 与 PyCharm CE 结合使用

    我正在尝试将 Selenium 与 PyCharm CE 一起使用 我已经使用 pip install Selenium 安装了 Selenium 并且可以通过终端使用它 但是当我尝试将它与 PyCharm 一起使用时 出现导入错误 Imp
  • Pandas如何将多个函数应用于数据框

    有没有办法像 DataFrameGroupBy agg 函数那样将函数列表应用于 DataFrame 中的每一列 我发现了一个丑陋的方法来做到这一点 df pd DataFrame dict one np random uniform 0
  • Android:如何停止监听电话监听器? [复制]

    这个问题在这里已经有答案了 可能的重复 Android 为什么 PhoneCallListener 在活动完成后仍然存在 https stackoverflow com questions 11666853 android why phon
  • 如何在 Google 地图中创建自定义地图?

    我正在尝试创建一个包含我家地图的 Google 地图应用程序 卧室 浴室 厨房等 使用 GPS 我会找到我现在在家里的位置 并尝试获取到我卧室的方向 步行距离 您可以使用Google的API来获取方向 我需要知道的是 如何添加我家的自定义地
  • 如何知道一个点是否在复杂的 3D 形状内(.ply 文件)

    我正在研究一个Java女巫项目真是要了我的命 经过几天在不同论坛上的研究 寻找我真正需要的东西 我来寻求你的帮助 我的数据 ply 文件 包含由许多三角形组成的 3D 形状 一个点 3D坐标 我想知道这个点是否包含在复杂的 3D 形状内 我
  • 在 grpc python 中处理异步流请求

    我试图了解如何使用双向流处理 grpc api 使用 Python API 假设我有以下简单的服务器定义 syntax proto3 package simple service TestService rpc Translate stre
  • Java并发锁和条件的使用

    我可以用object wait object notify and synchronized blocks解决生产者消费者类型的问题 同时我可以使用locks and conditions from java util concurrent
  • 表达式的类型必须是数组类型,但它解析为浮点数

    当我编写 Java 代码时 我遇到了困难 我觉得我不知何故把这个概念弄乱了 就像我不确定这一点 void setScore float sco sco score public void setScore float sco int id
  • 出于安全目的,您是否有理由不执行自己的算法来打乱 ID?

    我计划实现我自己的非常简单的 哈希 公式 为具有多个用户的应用程序添加一层安全性 我目前的计划如下 用户创建一个帐户 此时后端会生成一个 ID ID 通过公式运行 假设 ID 57 8926 36 7 或同样随机的东西 然后 我将新的用户
  • gstreamer 中的无缝视频循环

    我正在尝试使用 gstreamer 循环播放视频 它是 python 绑定 第一次尝试是hook EOSmessage并为管道生成搜索消息 import gi gi require version Gst 1 0 from gi repos
  • Java:将秒转换为分钟、小时和天[重复]

    这个问题在这里已经有答案了 任务是 输出应如下所示 最好回显输入 您输入了 500 000 秒 即 5 天 18 小时 53 分钟 20 秒 5天18 53 20小时 我该怎么做呢 最容易理解和做到的方法是什么 讲师还说 没有硬编码 我不太
  • 如何在Python中显示坐标网格线的变换?

    假设我有常规的笛卡尔坐标系 x y 并且我考虑一个矩形网格区域 D 分成小方块 我想看看域 D 如何在 Python 中的坐标变换 T x y gt u x y v x y 下映射 我正在寻找这样的东西 See here https mat
  • 捕获 SQLAlchemy 异常

    我可以使用什么捕获 SQLAlechmy 异常的上层异常 gt gt gt from sqlalchemy import exc gt gt gt dir exc ArgumentError CircularDependencyError

随机推荐

  • Python 文件的复制重命名以及xlsx文件中表格分开保存

    1 需要的头文件 import shutil import os import openpyxl 2 复制文件以及重命名 直接使用shutil库复制 重命名 移动即可 函数封装示例 source path 为全局变量被复制文件路径 dest
  • 计算机Java项目|学生成绩管理系统

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • 基于springboot+vue实现流浪动物救助平台演示【附项目源码+论文说明】

    基于springboot vue实现流浪动物救助平台演示 摘要 随着人们对于动物及环境保护的意识越来越强 流浪动物的救助与保护涉及到了健康卫生以及城市容貌等多个方面 流浪动物保护是一个全球性的问题 不同的国家和地区都出台了形式多样的保护办法
  • 计算机Java项目|电影购票系统

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • ssh:connect to host github.com port 22: Connection timed out

    解决流程 1 将github的端口由22改为443 ssh T p 443 git ssh github com 2 接着输入yes进行确认 The authenticity of host ssh github com 443 192 1
  • 计算机Java项目|基于SSM的篮球系列网上商城设计与实现

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • 基于springboot+vue实现食品安全管理系统演示【附项目源码+论文说明】

    基于springboot vue实现食品安全管理系统演示 摘要 食品行业同其他行业有很多的差别 食品行业不仅要管食品的生产和销售 还要管食品的库存和保质期 那么对于食品管理者来说 就存在着一定的难度 况且食品的种类复杂 存储条件各不相同 存
  • 春眠不觉晓,Java数据类型知多少?基础牢不牢看完本文就有数了

    俺滴座右铭是不在沉默中爆发 就在沉默中灭亡 一起加油学习 珍惜现在来之不易的学习时光吧 等工作之后 你就会发现 想学习真的需要挤时间 厚积薄发啦 我们知道Java是面向对象的静态型编程语言 在Java的世界里万物皆对象 但我认为是万物皆数据
  • 创业者自白|Mia Bao:唯有热爱,才能从“废墟”中蜕变出价值

    本采访转载自 财富 Fortune Magazine 创业者自白 Mia Bao 唯有热爱 才能从 废墟 中蜕变出价值 财富中文网 在充满机遇和挑战的区块链与Web3领域 涌现出许多富有冒险精神的年轻创业者 然而 在这个领域中 秉持热爱 并
  • APP开发毕业设计|ssm爱心小屋公益机构智慧管理APP

    作者主页 编程指南针 作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智
  • 基springboot+vue实现开放实验室管理系统子系统【附项目源码+论文说明】

    基springboot vue实现开放实验室管理系统子系统 摘要 信息技术永远是改变生活的第一种创新方式 各种行业的发展更是脱离不了科技化的支持 原本传统的行业正在被科技行业的切入悄悄的发生变化 就拿我们生活当中常见的事情举例而言 在外卖行
  • 最新整理Java面试八股文,大厂必备神器

    在此 我采访了数十名大厂的面试官和上百的的面试者 总结出了这一套Java面试八股文 这套八股文已经帮助了上百人拿到自己心仪的offer 我们先来看看这套八股文 Java基础面试八股文 操作系统中 heap 和 stack 的区别 什么是基于
  • 中小企业如何做好信息化规划?

    中小企业需不需要做信息化规划 什么时候做信息化规划比较好 企业的信息化规划 一定是越早越好 越快越好 因为信息化是一个过程 不是一个结果 它不是一天完成的事情 而是贯穿着企业经营管理的整个生命周期 而且在 企业创办初期或刚进入发展期的时候
  • 服务器VPS是什么意思?一文了解其含义与重要性

    在今天的数字时代 服务器扮演着至关重要的角色 它们是网站 应用程序和在线业务的基石 但是 你是否听说过VPS 本文将深入探讨什么是服务器VPS 以及为什么它在今天的互联网世界中如此重要 什么是服务器VPS 服务器的基本概念 在我们深入探讨V
  • Mysql中设置只允许指定ip能连接访问(可视化工具的方式)

    场景 Mysql中怎样设置指定ip远程访问连接 Mysql中怎样设置指定ip远程访问连接 navicat for mysql 设置只有某个ip可以远程链接 CSDN博客 前面设置root账户指定ip能连接访问是通过命令行的方式 如果通过可视
  • 计算机Java项目|基于SpringBoot个人空间平台的设计与实现

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • chrome浏览器无法在地址栏输入内容搜索问题解决--图文

    关于日常遇到的小问题解决记录一下 1 导航栏录入信息后跳转错误 2 解决办法 默认百度搜索引擎地址错误 百度正确的搜索格式是 http www baidu com s wd s chrome浏览器中百度的搜索格式是 http www bai
  • 2024史上最全Java面试八股文(带全部答案)

    今天要谈的主题是关于求职 求职是在每个技术人员的生涯中都要经历多次 对于我们大部分人而言 在进入自己心仪的公司之前少不了准备工作 有一份全面细致 面试题 将帮助我们减少许多麻烦 在跳槽季来临之前 特地做这个系列的文章 一方面帮助自己巩固下基
  • 面试官:分库分表后如何生成全局ID?

    分库分表后就不能使用自增 ID 来作为表的主键了 因为数据库自增 ID 只适用于单机环境 但如果是分布式环境 是将数据库进行分库 分表或数据库分片等操作时 那么数据库自增 ID 就会生成重复 ID 从而导致业务查询上的问题 所以此时 可以使
  • 详解Java信号量-Semaphore

    第1章 引言 大家好 我是小黑 今天 咱们一起来深入探讨一下Semaphore 在Java中 正确地管理并发是一件既挑战又有趣的事情 当谈到并发控制 大家可能首先想到的是synchronized关键字或者是ReentrantLock 但其实