java面試場景問題

還在補充,這幾天工作忙,閑了會把答案附上去,也歡迎各位大佬評論區討論

1.不用分布式鎖如何防重復提交

方法 1:基于唯一請求 ID(冪等 Token)

思路:前端生成 一個唯一的 requestId(如 UUID或者能表示本次請求的唯一標識字段),每次提交請求時帶上它。
后端使用 Redis存儲 requestId,如果已經存在,則拒絕處理。
實現:前端:每次提交請求時,生成一個 requestId:

javascript

const requestId = crypto.randomUUID(); // 生成唯一 ID
axios.post('/api/submit', { data, requestId });

后端java

@Autowired
private StringRedisTemplate redisTemplate;public ResponseEntity<String> submitRequest(String requestId, Data data) {Boolean isDuplicate = redisTemplate.opsForValue().setIfAbsent("request:" + requestId, "1", 10, TimeUnit.MINUTES);if (Boolean.FALSE.equals(isDuplicate)) {return ResponseEntity.status(HttpStatus.CONFLICT).body("重復提交");}try {// 處理業務邏輯process(data);return ResponseEntity.ok("提交成功");} finally {redisTemplate.delete("request:" + requestId); // 可選:若確保冪等性,可不刪除}
}

優點: ? 適用于分布式系統
? 性能好(基于 Redis 操作)
? Token 過期時間 防止長期占用

方法 2:數據庫唯一索引

思路:讓數據庫的唯一索引防止重復提交,常用于訂單號、業務唯一鍵。
實現
數據庫表添加唯一索引:

sql

ALTER TABLE orders ADD UNIQUE (order_no);

后端插入數據:

try {orderMapper.insert(order);
} catch (DuplicateKeyException e) {return ResponseEntity.status(HttpStatus.CONFLICT).body("重復提交");
}

優點: ? 數據庫級防重,最可靠
? 適合訂單、支付等業務場景
? 性能受限于數據庫,高并發需優化

方法 3:前端按鈕防抖

思路:提交后禁用按鈕,直到返回響應,防止用戶快速點擊。
實現

document.getElementById("submit-btn").addEventListener("click", function() {this.disabled = true;  // 禁用按鈕axios.post('/api/submit', { data }).then(response => alert(response.data)).finally(() => this.disabled = false); // 請求完成后恢復
});

優點: ? 簡單易行,無需改后端
? 前端可繞過,不適用于高安全性場景

方法 4:悲觀鎖(數據庫行鎖)

思路:通過 SELECT … FOR UPDATE 加行鎖,確保事務內數據不會被其他請求修改。
實現

@Transactional
public void submitOrder(Long orderId) {Order order = orderMapper.selectByIdForUpdate(orderId); // 加鎖if (order.getStatus() != OrderStatus.PENDING) {throw new IllegalStateException("訂單已處理");}order.setStatus(OrderStatus.PROCESSED);orderMapper.updateById(order);
}

優點: ? 確保單線程執行,避免重復
? 數據庫性能受影響,不適用于高并發

總結

![在這里插入圖片描述](https://i-blog.csdnimg.cn/direct/e48b7414c2c34517a705fe81d07393d9.png
)

推薦方案:
高并發系統:冪等 Token + Redis ?
數據庫事務業務:唯一索引 / 狀態機 ?
簡單防重:前端按鈕防抖 ?
如果并發壓力大,可以結合多種方案,例如:
Redis 冪等 Token + 數據庫唯一索引 🚀
前端防抖 + 后端冪等 Token 🔥

2.redis的哨兵模式是如何選舉的

Redis 的哨兵模式(Sentinel)用于監控 Redis 服務器,并在主服務器(Master)宕機時自動執行故障轉移(Failover)。哨兵模式的選舉過程主要發生在主服務器不可用時,選舉一個新的主服務器。以下是選舉的具體步驟:

  1. 發現主服務器故障
    每個哨兵(Sentinel)會定期向主服務器和從服務器發送 PING 命令,檢查它們的狀態。
    如果多個哨兵在 down-after-milliseconds 時間內沒有收到主服務器的響應,就會認為它 主觀下線(Subjectively Down, sDown)。
    當 大多數 哨兵都認定主服務器宕機時,主服務器就會進入 客觀下線(Objectively Down, oDown) 狀態,觸發故障轉移。
  2. 哨兵選舉領導者
    當主服務器 oDown 后,需要一個哨兵來執行故障轉移,因此哨兵之間需要進行 Raft 算法 類似的選舉流程:

所有哨兵都可以參與選舉,嘗試成為領導者(Leader)。
每個哨兵向其他哨兵發送 SENTINEL is-master-down-by-addr 請求,詢問它們是否同意自己成為領導者。
其他哨兵如果還沒有投票,則會同意投票給該請求的哨兵。
如果一個哨兵獲得超過一半的票數(多數派),就會成為領導者。
3. 選擇新的主服務器
領導者哨兵會從現有的從服務器中選擇一個最合適的來提升為新的主服務器:

選擇 復制進度最接近主服務器 的從服務器(偏移量最大)。
如果多個從服務器復制進度相同,選擇 ID 最小 的。
如果沒有合適的從服務器,則失敗,等待下一輪選舉。
4. 執行故障轉移
領導者哨兵發送 slaveof no one 命令,讓選中的從服務器成為新的主服務器。
讓其他從服務器執行 slaveof <new_master>,將它們的主服務器指向新的主服務器。
更新配置信息,廣播新的主服務器地址給所有 Redis 客戶端。
5. 恢復監控
整個集群穩定后,哨兵繼續監控新的主服務器和從服務器,準備處理下一次故障。
通過這種選舉機制,Redis 的哨兵模式能夠自動檢測主服務器故障,并確保集群能夠繼續運行。

3.線程池的原理

  1. 線程池的概念
    線程池(Thread Pool)是一種用于管理和復用線程的技術,它維護了一組可復用的線程,避免了頻繁創建和銷毀線程的開銷,從而提高程序的執行效率。

  2. 線程池的核心組成
    線程池主要由以下幾個核心部分組成:

線程隊列(BlockingQueue)
用于存放等待執行的任務。常見的隊列類型:

無界隊列(LinkedBlockingQueue):適用于任務量大但不會超出系統資源的情況。
有界隊列(ArrayBlockingQueue):適用于控制任務數量,防止資源耗盡。
優先隊列(PriorityBlockingQueue):任務可根據優先級執行。
核心線程數(Core Pool Size)

線程池初始化后,線程數不超過核心線程數時,即使空閑,也不會銷毀。
最大線程數(Maximum Pool Size)

當任務數量超過核心線程數時,線程池可以臨時創建額外的線程,但不會超過最大線程數。
任務拒絕策略(Rejection Policy)
當線程池達到最大線程數且任務隊列已滿時,新任務將被拒絕。常見策略:

AbortPolicy(默認):拋出異常。
CallerRunsPolicy:調用線程自己執行任務,降低任務提交速率。
DiscardPolicy:直接丟棄任務,不處理也不拋出異常。
DiscardOldestPolicy:丟棄隊列中最早的任務,再嘗試執行新任務。
線程工廠(ThreadFactory)

用于創建線程,可以自定義線程命名、設置守護線程等。
存活時間(Keep Alive Time)

當線程數超過核心線程數時,多余的空閑線程會在超過該時間后被銷毀。
3. 線程池的工作流程
任務提交到線程池。
如果當前運行線程數小于核心線程數,直接創建新線程執行任務。
如果核心線程數已滿,則任務進入隊列等待。
若隊列已滿且線程數小于最大線程數,則創建新線程執行任務。
若線程數達到最大值且任務隊列也滿了,則觸發任務拒絕策略。
線程執行完任務后,若線程數超過核心線程數,多余的空閑線程會在 keepAliveTime 超過后被銷毀。
4. 線程池的優點
提高性能:減少線程創建和銷毀的開銷。
提高資源利用率:合理分配線程,避免資源浪費。
控制并發:防止創建過多線程導致系統資源耗盡。
5. 線程池的應用
在 Java 中,ExecutorService 提供了常見的線程池實現:

ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(() -> {System.out.println("任務執行:" + Thread.currentThread().getName());
});
executor.shutdown();
  1. 自定義線程池
    使用 ThreadPoolExecutor 自定義線程池:
ExecutorService threadPool = new ThreadPoolExecutor(2,                // 核心線程數5,                // 最大線程數60,               // 線程空閑存活時間TimeUnit.SECONDS, // 時間單位new LinkedBlockingQueue<>(10), // 任務隊列Executors.defaultThreadFactory(), // 線程工廠new ThreadPoolExecutor.AbortPolicy() // 拒絕策略
);

4.spring的spi和dubbo的spi機制是什么?

Spring 的 SPI(Service Provider Interface) 主要基于 Java 原生的 java.util.ServiceLoader 機制,并在此基礎上進行了增強。它主要用于加載和擴展 Spring 組件,如 SpringFactoriesLoader。

1. Java SPI 機制

Java 提供 java.util.ServiceLoader,用于加載 META-INF/services/ 目錄下的服務配置文件。
這個配置文件的命名規則是接口的全限定名,內容是具體的實現類。

示例
定義 SPI 接口

public interface MyService {void execute();
}//提供實現
public class MyServiceImpl implements MyService {@Overridepublic void execute() {System.out.println("MyServiceImpl executed");}
}

在 META-INF/services/ 目錄下,創建文件 com.example.MyService,內容如下:

com.example.MyServiceImpl

使用 ServiceLoader 進行加載:

ServiceLoader<MyService> loader = ServiceLoader.load(MyService.class);
for (MyService service : loader) {service.execute();
}
2. Spring 的 SPI

Spring 在 Java SPI 機制基礎上,增加了 SpringFactoriesLoader,用于從 META-INF/spring.factories 文件中加載擴展組件。

Spring SPI 加載方式:

主要通過 org.springframework.core.io.support.SpringFactoriesLoader 進行加載。
讀取 META-INF/spring.factories 配置文件,該文件的內容格式為:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration

在 Spring Boot 自動裝配(AutoConfiguration)中,大量使用了該機制。
示例

1.在 spring.factories 文件中配置:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.MyAutoConfiguration

2.MyAutoConfiguration 類:

@Configuration
public class MyAutoConfiguration {@Beanpublic MyService myService() {return new MyServiceImpl();}
}

3.Spring Boot 在啟動時,會通過 SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, classLoader) 自動加載 MyAutoConfiguration 類,從而完成自動配置。

3.Dubbo 的 SPI 機制

Dubbo 也使用了 SPI 機制,但相比 Java SPI 進行了增強,主要特點包括:

自定義 SPI 機制:Dubbo 提供了 ExtensionLoader,替代 Java 的 ServiceLoader,支持 AOP、IoC 和自適應擴展等功能。
META-INF/dubbo/ 目錄:Dubbo 的 SPI 機制約定配置文件放在 META-INF/dubbo/ 或 META-INF/services/ 目錄下。
@SPI 注解:Dubbo 允許在接口上使用 @SPI 進行標注,指明默認實現。
支持 @Adaptive 注解:Dubbo 支持自適應擴展,能夠根據參數動態選擇實現類。

  1. Dubbo SPI 使用方式
    1>定義 SPI 接口
import org.apache.dubbo.common.extension.SPI;@SPI("defaultImpl") // 指定默認實現
public interface MyService {void execute();
}

2>提供多個實現

public class DefaultImpl implements MyService {@Overridepublic void execute() {System.out.println("Executing Default Implementation");}
}public class AdvancedImpl implements MyService {@Overridepublic void execute() {System.out.println("Executing Advanced Implementation");}
}

3>配置 META-INF/dubbo/com.example.MyService

defaultImpl=com.example.DefaultImpl
advancedImpl=com.example.AdvancedImpl

4>通過 Dubbo 的 ExtensionLoader 加載

ExtensionLoader<MyService> loader = ExtensionLoader.getExtensionLoader(MyService.class);
MyService service = loader.getDefaultExtension(); // 獲取默認實現
service.execute();MyService advancedService = loader.getExtension("advancedImpl"); // 獲取指定實現
advancedService.execute();
  1. Dubbo SPI 的增強點
    默認實現:@SPI(“defaultImpl”) 指定默認實現。
    自動注入:Dubbo 的擴展點支持 IoC,可以自動注入依賴。
    自適應擴展:@Adaptive 允許根據運行時參數動態選擇實現。
    Wrapper 擴展:支持 AOP 方式的擴展,如日志增強。

總結
在這里插入圖片描述
Spring SPI 主要用于 Spring Boot 自動裝配。
Dubbo SPI 主要用于服務擴展,提供了更強的動態適配能力。
Dubbo SPI 機制在性能、可擴展性和動態適應方面,比 Spring 和 Java SPI 機制更加強大。

5.流量激增,大批量數據如何處理?

  1. 數據分片與分區
    數據庫分片(Sharding):將數據拆分到多個數據庫實例上,減少單個數據庫的壓力。
    分區表(Partitioning):對大表進行分區存儲,提高查詢性能,例如按時間、地域等劃分。
  2. 高效的緩存策略
    CDN(內容分發網絡):對于靜態資源(圖片、視頻、文件等),使用CDN分發可減少源站壓力。
    Redis/Memcached:對于熱點數據,將查詢結果緩存,減少數據庫訪問次數。
    本地緩存:在應用層使用LRU緩存避免頻繁訪問遠程存儲。
  3. 異步處理與消息隊列
    消息隊列(Kafka、RabbitMQ、RocketMQ):削峰填谷,將高并發請求轉換為異步任務,提高吞吐量。
    任務隊列(Celery、Sidekiq):對于非實時數據處理(如日志分析、統計計算),可以異步執行。
  4. 擴展架構
    水平擴展(Scale Out):增加服務器數量,通過負載均衡(Nginx、HAProxy)分發流量。
    垂直擴展(Scale Up):提升單機性能,如升級CPU、內存、磁盤IO能力。
  5. 數據流處理
    流式計算(Flink、Spark Streaming、Storm):用于實時數據處理,避免批量計算的延遲問題。
    批處理(Hadoop、Spark):適用于大規模離線分析任務。
  6. 數據庫優化
    索引優化:合理使用B+樹索引、哈希索引等加速查詢。
    SQL優化:避免N+1查詢,使用JOIN優化查詢結構。
    讀寫分離:主從數據庫架構,分離讀寫操作,提高查詢性能。
  7. 日志及監控
    ELK(Elasticsearch + Logstash + Kibana):用于日志分析,監測異常流量。
    Prometheus + Grafana:監控系統狀態,及時發現瓶頸。
    通過以上策略,可以高效應對流量激增和大批量數據處理,提高系統穩定性和響應速度。

6.rabbitmq如何防止重復消費,高并發情況下

  1. 確保手動 ACK
    避免使用自動 ACK,確保消息處理完畢后再確認

? 正確做法(手動 ACK)

channel.basicConsume(QUEUE_NAME, false, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope,AMQP.BasicProperties properties, byte[] body) throws IOException {try {String message = new String(body, "UTF-8");processMessage(message); // 處理消息// 處理完成后手動確認channel.basicAck(envelope.getDeliveryTag(), false);} catch (Exception e) {// 處理失敗,拒絕消息并重新放回隊列channel.basicNack(envelope.getDeliveryTag(), false, true);}}
});

📌 說明
autoAck=false (手動 ACK)
basicAck() (成功后確認消息已處理)
basicNack() (失敗后重新入隊)

  1. 業務層去重
    即使 RabbitMQ 保障**“至少一次”(At Least Once)**投遞,仍可能發生重復消費,因此需要在業務層去重。

? 方法 1:數據庫唯一約束
可以使用數據庫的唯一索引字段,如訂單號 order_id:

INSERT INTO orders (order_id, user_id, amount) 
VALUES ('msg_123456', 'user_001', 100) 
ON DUPLICATE KEY UPDATE order_id=order_id;
如果 order_id 已存在,則不會插入新的記錄。

? 方法 2:Redis 去重
使用 Redis SETNX(防止短時間內重復處理)

public boolean isProcessed(String messageId) {String key = "msg_" + messageId;Boolean success = redisTemplate.opsForValue().setIfAbsent(key, "1", 60, TimeUnit.SECONDS);return success != null && !success;
}public void processMessage(String message) {if (isProcessed(message)) {System.out.println("消息已處理,跳過: " + message);return;}// 業務邏輯處理
}
  1. 設置消息 TTL + 死信隊列(DLX)
    防止重復消費時死循環

? 設置消息 TTL

Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", 60000); // 60s 后消息過期
args.put("x-dead-letter-exchange", "dlx_exchange"); // 指定死信交換機
channel.queueDeclare("task_queue", true, false, false, args);

? 死信隊列(DLX)
當消息失敗多次后,可以轉移到死信隊列,避免重復消費:

args.put("x-dead-letter-routing-key", "dlx_routing_key");
  1. 限制消費者并發數
    如果消費者并發過高,可能會導致 RabbitMQ 消息重復投遞,可以限制每個消費者最多只能預取 1 條消息:
channel.basicQos(1); // 每個消費者一次只處理 1 條消息
  1. 生產者端消息確認
    RabbitMQ 提供 Confirm 機制,確保消息不會丟失
channel.confirmSelect(); // 開啟發布確認模式channel.basicPublish("", "task_queue", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));// 等待確認
if (!channel.waitForConfirms()) {System.out.println("消息發送失敗");
}

總結
? 手動 ACK 機制(避免自動 ACK,確保消息處理完畢后才確認)
? 業務去重(數據庫唯一索引,Redis SETNX)
? TTL + 死信隊列(防止重復消費導致的死循環)
? 限制并發數(basicQos(1) 限制每個消費者最多消費 1 條)
? 發布確認(waitForConfirms() 確保消息可靠投遞)

使用這些優化方法,可以有效防止 RabbitMQ 在 高并發情況下的重復消費,保障消息一致性和系統穩定性!🚀

7消息堆積如何處理?

在 RabbitMQ 高并發環境下,如果消息處理速度趕不上生產速度,容易導致 消息堆積,最終可能引發 隊列溢出、服務器崩潰 等問題。這里介紹 消息堆積的原因分析 以及 有效的解決方案。
? 解決方案

  1. 增加消費者并發數
    方法:
    增加 消費者實例(多個 Worker 并發消費)
    調整 預取數 prefetch_count,避免一個消費者一次性接收過多消息
    📌 示例(Java 代碼:增加并發消費者)
channel.basicQos(10);  // 每個消費者最多處理 10 條消息

這樣可以讓消費者更快地處理消息,減少隊列堆積。

  1. 使用消息分片 & 負載均衡
    當單個隊列壓力過大時,可以通過 多隊列 + 負載均衡 分擔流量:
    方法 1:按 消息特性 分片(如訂單隊列、支付隊列、庫存隊列)
    方法 2:多個消費者監聽 不同的隊列 處理同一類任務
    方法 3:使用 交換機(Exchange) 進行路由
    📌 示例(不同消費者監聽不同的隊列)
channel.queueDeclare("order_queue", true, false, false, null);
channel.queueDeclare("payment_queue", true, false, false, null);

優點:避免某一個隊列因負載過大而導致 RabbitMQ 掛掉。

  1. 啟用 RabbitMQ 集群
    如果 RabbitMQ 單節點性能不足,可以使用 RabbitMQ 集群,提高系統的吞吐能力:
    鏡像隊列模式:保證高可用
    分布式隊列模式:多個 RabbitMQ 節點共同處理消息
    📌 示例(啟用集群)
rabbitmqctl join_cluster rabbit@node2

優點:多個 RabbitMQ 服務器 分擔流量,避免單點壓力過大。

  1. 配置消息 TTL + 死信隊列
    如果消息長時間堆積,可以設置 消息過期時間(TTL),并把未處理的消息轉入 死信隊列(DLX)。

📌 示例(配置 TTL + DLX)

Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", 60000); // 消息存活 60s
args.put("x-dead-letter-exchange", "dlx_exchange"); // 過期消息轉入死信隊列
channel.queueDeclare("task_queue", true, false, false, args);

優點:

  • 限制消息存活時間,防止無用消息無限堆積。
  • 過期消息進入 死信隊列,避免影響正常業務。
  1. 限流(限流+降級)
    如果生產者產生消息過快,可以限制生產速度,或直接丟棄部分非核心消息。

限流方式:

  • RabbitMQ basic.qos 控制流速
  • Kafka 或 Redis 作為緩沖層
  • 應用層限流(如令牌桶、漏桶算法)
    📌 示例(使用 basic.qos 進行流量控制)
channel.basicQos(5);  // 限制每個消費者每次最多消費 5 條

優點:可以防止 RabbitMQ 被瞬時高并發流量壓垮。

  1. 監控 & 自動擴展
  • 使用 RabbitMQ 監控工具(Prometheus + Grafana / RabbitMQ Management)
  • 設置自動擴容機制(Kubernetes HPA)
    📌 示例(監控 RabbitMQ 隊列長度)
rabbitmqctl list_queues name messages_ready messages_unacknowledged

如果隊列長度超過閾值,可以 動態增加消費者,提高處理能力。
🔥 總結
在這里插入圖片描述
如果你的 RabbitMQ 消息已經堆積過多,可以:

  • 臨時增加消費者實例(短期緩解)
  • 快速清理過期/無用消息(避免資源占滿)
  • 優化消息分片 & 負載均衡(長期解決)

8.用過那些監控ivm的工具?

IVM(Intelligent Virtual Machine,智能虛擬機)監控 需要關注 CPU、內存、磁盤、網絡 以及 應用服務 的健康狀態。常見的 IVM 監控工具有:
在這里插入圖片描述
? 如何實現 IVM 監控

  1. 使用 Prometheus + Grafana 監控 IVM
    架構:
  • Node Exporter(采集虛擬機 CPU、內存、磁盤、網絡)
  • Prometheus(存儲 & 報警)
  • Grafana(可視化)
    📌 步驟 1?? 安裝 Node Exporter(虛擬機監控)
wget https://github.com/prometheus/node_exporter/releases/latest/download/node_exporter-linux-amd64.tar.gz
tar -xzf node_exporter-linux-amd64.tar.gz
cd node_exporter-*
./node_exporter &

2?? 配置 Prometheus 采集虛擬機數據 編輯 prometheus.yml:

yaml
scrape_configs:- job_name: 'ivm-monitor'static_configs:- targets: ['192.168.1.100:9100']  # 監控 IVMIP

3?? 運行 Prometheus

./prometheus --config.file=prometheus.yml

4?? 配置 Grafana 可視化

  • 在 Grafana 添加數據源(Prometheus)
  • 使用 Node Exporter 監控儀表盤展示 CPU、內存、磁盤使用率
  1. 使用 Zabbix 監控 IVM
    1?? 安裝 Zabbix Agent 到 IVM
sudo apt install zabbix-agent
sudo systemctl start zabbix-agent
sudo systemctl enable zabbix-agent

2?? 配置 Zabbix Server 在 /etc/zabbix/zabbix_agentd.conf 添加:

Server=192.168.1.200  # Zabbix 服務器 IP

3?? 在 Zabbix Web UI 中添加 IVM 主機

  • 配置 CPU、內存、網絡監控
  • 設置告警閾值(如 CPU 使用率 > 80% 發送告警)
  1. 使用 ELK 監控 IVM 日志
    1?? 安裝 Filebeat 采集日志
sudo apt install filebeat

2?? 配置 Filebeat 發送到 Elasticsearch

output.elasticsearch:hosts: ["192.168.1.200:9200"]

3?? 使用 Kibana 可視化 IVM 日志

🚀 總結

  • 大規模 IVM 監控 👉 Prometheus + Grafana
  • 企業級穩定監控 👉 Zabbix / Nagios
  • 日志監控 👉 ELK
  • SaaS 監控 👉 Datadog / New Relic
    如果是 高并發分布式 IVM 監控,推薦 Prometheus + Grafana,結合 告警 & 自動擴展,確保系統穩定!💡

9.常用的設計模式有哪些?怎么用的?

設計模式(Design Patterns) 是軟件開發中的常見問題解決方案,主要分為 三大類:

  • 創建型模式(解決對象創建問題)
  • 結構型模式(解決類和對象的組合問題)
  • 行為型模式(解決對象交互問題)
    🔹 1. 創建型模式
    ? 1.1 單例模式(Singleton)
    作用:確保一個類只有一個實例,并提供全局訪問點
    應用場景:數據庫連接池、線程池、日志系統

📌 示例(懶漢式,線程安全)

public class Singleton {private static volatile Singleton instance;  // 防止指令重排private Singleton() {}  // 私有構造函數,防止外部實例化public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

? 1.2 工廠模式(Factory Pattern)
作用:提供一個創建對象的接口,而不是直接實例化類
應用場景:數據庫連接、日志記錄器

📌 示例

// 1. 定義接口
interface Product {void create();
}// 2. 具體產品實現
class ConcreteProductA implements Product {public void create() { System.out.println("創建產品 A"); }
}class ConcreteProductB implements Product {public void create() { System.out.println("創建產品 B"); }
}// 3. 工廠類
class Factory {public static Product getProduct(String type) {if ("A".equals(type)) return new ConcreteProductA();else if ("B".equals(type)) return new ConcreteProductB();return null;}
}// 4. 使用工廠
Product product = Factory.getProduct("A");
product.create();

🔹 2. 結構型模式
? 2.1 適配器模式(Adapter Pattern)
作用:把一個接口轉換成客戶端期望的另一個接口
應用場景:兼容老代碼、新舊接口對接

📌 示例

// 1. 目標接口
interface Target {void request();
}// 2. 被適配者(舊接口)
class Adaptee {void specificRequest() { System.out.println("調用舊接口"); }
}// 3. 適配器
class Adapter implements Target {private Adaptee adaptee = new Adaptee();public void request() { adaptee.specificRequest(); }
}// 4. 使用適配器
Target adapter = new Adapter();
adapter.request();

? 2.2 裝飾器模式(Decorator Pattern)
作用:動態擴展類的功能,而不修改原代碼
應用場景:日志增強、數據加密、I/O 流

📌 示例

// 1. 定義接口
interface Component {void operation();
}// 2. 具體組件
class ConcreteComponent implements Component {public void operation() { System.out.println("基礎功能"); }
}// 3. 裝飾器基類
class Decorator implements Component {protected Component component;public Decorator(Component component) { this.component = component; }public void operation() { component.operation(); }
}// 4. 具體裝飾器
class ConcreteDecorator extends Decorator {public ConcreteDecorator(Component component) { super(component); }public void operation() {super.operation();System.out.println("擴展功能");}
}// 5. 使用裝飾器
Component decorated = new ConcreteDecorator(new ConcreteComponent());
decorated.operation();

🔹 3. 行為型模式
? 3.1 觀察者模式(Observer Pattern)
作用:一對多依賴,當一個對象狀態改變,所有依賴對象自動更新
應用場景:事件監聽、消息推送

📌 示例

import java.util.ArrayList;
import java.util.List;// 1. 觀察者接口
interface Observer {void update(String message);
}// 2. 具體觀察者
class User implements Observer {private String name;public User(String name) { this.name = name; }public void update(String message) {System.out.println(name + " 收到消息: " + message);}
}// 3. 主題(被觀察者)
class Subject {private List<Observer> observers = new ArrayList<>();public void addObserver(Observer observer) { observers.add(observer); }public void notifyObservers(String message) {for (Observer observer : observers) observer.update(message);}
}// 4. 測試
Subject subject = new Subject();
Observer user1 = new User("張三");
Observer user2 = new User("李四");
subject.addObserver(user1);
subject.addObserver(user2);
subject.notifyObservers("系統升級");

? 3.2 策略模式(Strategy Pattern)
作用:定義一系列算法,讓它們可以互換,避免 if-else 代碼膨脹
應用場景:支付方式、數據壓縮、權限驗證

📌 示例

// 1. 策略接口
interface Strategy {void execute();
}// 2. 具體策略
class ConcreteStrategyA implements Strategy {public void execute() { System.out.println("執行策略 A"); }
}class ConcreteStrategyB implements Strategy {public void execute() { System.out.println("執行策略 B"); }
}// 3. 上下文(使用策略)
class Context {private Strategy strategy;public void setStrategy(Strategy strategy) { this.strategy = strategy; }public void executeStrategy() { strategy.execute(); }
}// 4. 測試
Context context = new Context();
context.setStrategy(new ConcreteStrategyA());
context.executeStrategy();
context.setStrategy(new ConcreteStrategyB());
context.executeStrategy();

🔥 總結
在這里插入圖片描述

10.xxl-job如果任務處理不完怎么辦?

🔍 任務堆積的原因分析

  • 任務執行時間過長(業務邏輯耗時過多、數據庫查詢慢)
  • 任務并發數太少(單個執行器線程數限制)
  • 任務調度間隔過短(調度頻率高,任務還未執行完就來了新的)
  • 任務失敗未重試(導致部分任務一直未完成)
  • 執行器負載過高(CPU、內存資源耗盡)
    ? 解決方案
  1. 增加任務并發數
    如果執行器并發數太少,任務處理能力有限,可以通過 線程池 提高并發。

📌 方法 1:配置 XXL-Job 線程池

修改 XXL-Job 執行器配置,提高 xxl.job.executor.logretentiondays

xxl.job.executor.logretentiondays=30
xxl.job.executor.threadpool=20

Java 代碼示例(使用線程池)

@XxlJob("parallelJobHandler")
public void parallelJobHandler() throws Exception {ExecutorService executorService = Executors.newFixedThreadPool(10); // 增加線程池for (int i = 0; i < 10; i++) {executorService.submit(() -> {System.out.println("處理任務:" + Thread.currentThread().getName());});}executorService.shutdown();
}
  1. 增加執行器機器
    如果任務量特別大,單個 Executor(執行器) 處理不過來,可以 水平擴展,增加多臺機器。

📌 方法:配置 XXL-Job 多個執行器

  • 在 Nginx 或負載均衡 中配置多個 XXL-Job 執行器
  • 在 xxl-job-admin 配置多個 Executor
  • 動態擴容:可以使用 Kubernetes(K8s)+ HPA 自動擴展實例
    📌 示例(多個執行器注冊)
xxl.job.executor.address=http://192.168.1.100:9999,http://192.168.1.101:9999
  1. 任務分片(Sharding)
    如果任務處理不完,可以 拆分任務,讓多個執行器同時處理不同數據片段。

📌 方法:使用 XXL-Job 自帶的 Sharding

@XxlJob("shardingJobHandler")
public void shardingJobHandler() throws Exception {int shardIndex = XxlJobHelper.getShardIndex(); // 當前執行器分片索引int shardTotal = XxlJobHelper.getShardTotal(); // 總分片數System.out.println("執行分片:" + shardIndex + "/" + shardTotal);
}

作用:如果有 10000 條數據,可以分 10 片,每個執行器處理 1000 條,提升任務吞吐量。

  1. 任務超時 & 限流
    如果任務執行時間過長,導致后續任務堆積,可以:

設置任務超時時間
限制最大并發數
📌 方法:配置 XXL-Job 超時 & 并發

@XxlJob(value = "timeoutJobHandler", init = "initMethod", destroy = "destroyMethod", timeout = 5000, concurrent = false)
public void timeoutJobHandler() throws Exception {Thread.sleep(6000); // 模擬超時
}
timeout = 5000:超時 5 秒后強制結束任務
concurrent = false:不允許并發執行,防止任務堆積
  1. 失敗重試
    如果任務失敗,可能會導致數據未處理完。可以開啟 失敗重試,讓 XXL-Job 自動嘗試執行。

📌 方法:在 XXL-Job 控制臺配置

  • 重試次數:默認 3 次
  • 失敗策略:
    • 失敗重試(RETRY)
    • 失敗報警(FAIL_ALARM)
    • 丟棄后續任務(DISCARD_LATER)
  1. 任務排隊(消息隊列)
    如果任務量超大,可以引入 消息隊列(MQ) 進行流量削峰。

📌 方法:使用 RabbitMQ / Kafka 進行異步處理

@XxlJob("mqJobHandler")
public void mqJobHandler() throws Exception {String message = "任務數據";rabbitTemplate.convertAndSend("taskQueue", message);
}

讓 XXL-Job 只負責寫入 MQ,執行器異步消費,防止任務堆積。
🔥 總結
在這里插入圖片描述
📌 綜合優化:
? 短期優化 👉 線程池、任務分片、超時處理
? 長期優化 👉 負載均衡、多執行器、異步消息隊列

如果 XXL-Job 任務一直堆積,建議結合 任務分片 + 多執行器 + MQ 方案,確保高并發場景下任務穩定運行!🚀

11.spring事務失效情況,傳播機制,如何保證事務不失效

🔹 1. Spring 事務失效的常見原因
在 Spring 中,事務由 @Transactional 注解管理,但在某些情況下事務可能會失效。常見失效情況包括:
在這里插入圖片描述

🔹 2. 事務傳播機制(Transaction Propagation)
Spring 事務提供 7 種事務傳播機制,主要用于嵌套調用時事務的行為控制:
在這里插入圖片描述
📌 示例

@Service
public class OrderService {@Transactional(propagation = Propagation.REQUIRED)public void createOrder() {userService.addUser();  // 事務加入當前事務paymentService.processPayment();  // 事務加入當前事務}
}

🔹 3. 如何保證事務不失效
為了確保事務能夠正常生效,推薦采取以下措施:

? 1. @Transactional 方法必須是 public
📌 錯誤示例(私有方法無效)

@Service
public class MyService {@Transactionalprivate void saveData() { // ? 無效// 事務不會生效}
}

📌 正確示例

@Service
public class MyService {@Transactionalpublic void saveData() { // ? 必須是 public// 事務正常生效}
}

? 2. 確保 @Transactional 方法是由 Spring 托管的 Bean 調用
📌 錯誤示例(內部調用失效)

@Service
public class MyService {@Transactionalpublic void methodA() {methodB();  // ? 內部調用,事務失效}@Transactionalpublic void methodB() {// 事務不會生效}
}

📌 正確示例

@Service
public class MyService {@Transactionalpublic void methodA() {((MyService) AopContext.currentProxy()).methodB();  // ? 通過代理調用}@Transactionalpublic void methodB() {// 事務正常生效}
}

? 3. 事務異常必須是 RuntimeException
📌 錯誤示例(捕獲異常后事務不回滾)

java
復制
編輯
@Transactional
public void updateData() {
try {
// 業務邏輯
} catch (Exception e) { // ? 事務不會回滾
e.printStackTrace();
}
}
📌 正確示例

java
復制
編輯
@Transactional
public void updateData() {
try {
// 業務邏輯
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); // ? 手動回滾
}
}
? 4. 多線程事務控制
📌 錯誤示例(子線程不繼承事務)

@Transactional
public void process() {new Thread(() -> saveData()).start(); // ? 事務不會生效
}

📌 正確示例

@Transactional
public void process() {CompletableFuture.runAsync(() -> saveData(), Executors.newFixedThreadPool(5)); // ? 線程池事務
}

? 5. 事務嵌套 & Propagation.REQUIRES_NEW
如果主事務和子事務相互獨立,可以使用 REQUIRES_NEW。

📌 示例

@Service
public class OrderService {@Transactional(propagation = Propagation.REQUIRED)public void createOrder() {paymentService.processPayment();  // 事務 A}
}@Service
public class PaymentService {@Transactional(propagation = Propagation.REQUIRES_NEW)public void processPayment() {// 事務 B,獨立提交,不受主事務影響}
}

🔥 總結
在這里插入圖片描述
📌 最佳實踐

  • 所有 @Transactional 方法必須是 public
  • 確保方法是由 Spring 管理的 Bean 調用(避免內部調用)
  • 拋出的異常必須是 RuntimeException,或手動 setRollbackOnly()
  • 多線程時要手動綁定事務
  • 事務傳播機制要合理選擇(REQUIRES_NEW / NESTED 等)

12.dubbo和openfeiqn的區別?

13.nacos支持負載均衡嗎,策略是什么?

14.了解過逃逸分析嗎?

15.hashmap底層結構,什么時間會形成鏈表,idk1.8前后有啥區別

16.jvm內存結構,新生代的垃圾回收算法,老年代的垃圾回收算法

17.如何創建線程,start方法可不可以調兩次,一個線程如何喚起另一個線程。

18.syncornized和Lock有什么區別

19.volatile關鍵字的實現原理

20.線程池的基本原理,具體參數是什么

21.redis線程模型,redis的主從、哨兵、集群模式區別

22.消息堆積如何處理,消息重復消費如何避免

23.使用過的設計模式

24.mysql的索引原理

25.sql優化方法

26.springcloud用過哪些組件

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/70676.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/70676.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/70676.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Windows11安裝GPU版本Pytorch2.6教程

1: 準備工作 針對已經安裝好的Windows11系統&#xff0c;先檢查Nvidia驅動和使用的CUDA版本情況。先打開Windows PowerShell&#xff0c;通過nvidia-smi命令查看GPU的情況&#xff0c;結果如下圖1所示&#xff0c;從結果中可知使用的CUDA版本為12.8。 圖1&#xff1a;檢測安裝…

深入了解Text2SQL開源項目(Chat2DB、SQL Chat 、Wren AI 、Vanna)

深入了解Text2SQL開源項目&#xff08;Chat2DB、SQL Chat 、Wren AI 、Vanna&#xff09; 前言 1.Chat2DB2.SQL Chat3.Wren AI4.Vanna 前言 在數據驅動決策的時代&#xff0c;將自然語言查詢轉化為結構化查詢語言&#xff08;SQL&#xff09;的能力變得日益重要。無論是小型…

go 環境準備

配置路徑&#xff1a; GOROOT&#xff1a;D:\GoGOPATH&#xff1a;go的工作目錄 D:\workspacego 驗證版本&#xff1a;go version 配置第三方倉庫&#xff1a; GO111MODULE&#xff1a;開啟mod模式GOPROXY&#xff1a;go語言三方庫地址GOSUMDB&#xff1a;go語言軟件包的M…

Qt/C++項目積累:3.日志管理系統 - 3.1 項目介紹

在實際工程項目中&#xff0c;日志系統無疑是比較重要地分析問題的手段&#xff0c;常用的一般是將其寫入到日志文件中&#xff0c;或者寫入數據庫文件&#xff0c;進行分析&#xff0c;而工程人員或者開發人員需要實時查看日志&#xff0c;可能不太方便&#xff0c;于是就需要…

netty十八羅漢之——挖耳羅漢(Decoder)

佛教中除不聽各種淫邪聲音之外&#xff0c;更不可聽別人的秘密。因他論耳根最到家&#xff0c;故取挖耳之形&#xff0c;以示耳根清凈。 來看看netty的核心組件解碼器Decoder Decoder的作用半包&#xff0c;粘包問題從模板和裝飾器模式看Decoder解碼原理 1.Decoder作用 最根本…

51單片機學習之旅——定時器

打開軟件 1與其它等于其它&#xff0c;0與其它等于0 1或其它等于1&#xff0c;0或其它等于其它 TMODTMOD&0xF0;//0xF01111 0000進行與操作&#xff0c;高四位保持&#xff0c;低四位清零&#xff0c;高四位定時器1&#xff0c;低四位定時器0 TMODTMOD|0x01;//0x010000 0…

內容中臺重構智能服務:人工智能技術驅動精準決策

內容概要 現代企業數字化轉型進程中&#xff0c;內容中臺與人工智能技術的深度融合正在重構智能服務的基礎架構。通過整合自然語言處理、知識圖譜構建與深度學習算法三大技術模塊&#xff0c;該架構實現了從數據采集到決策輸出的全鏈路智能化。在數據層&#xff0c;系統可對接…

【redis】redis內存管理,過期策略與淘汰策略

一&#xff1a;Redis 的過期刪除策略及處理流程如下&#xff1a; 1. 過期刪除策略 Redis 通過以下兩種策略刪除過期鍵&#xff1a; 1.1 惰性刪除 觸發時機&#xff1a;當客戶端訪問某個鍵時&#xff0c;Redis 會檢查該鍵是否過期。執行流程&#xff1a; 客戶端請求訪問鍵。…

tp6上傳文件大小超過了最大值+驗證文件上傳大小和格式函數

問題&#xff1a; 最近用tp6的文件上傳方法上傳文件時報文件過大錯誤。如下所示&#xff1a; $file $this->request->file(file);{"code": 1,"msg": "上傳文件大小超過了最大值&#xff01;","data": {"code": 1,&q…

Kreuzberg:本地OCR+多格式解析!Kreuzberg如何用Python暴力提取30+文檔格式?程序員看完直呼內行!

嗨&#xff0c;大家好&#xff0c;我是小華同學&#xff0c;關注我們獲得“最新、最全、最優質”開源項目和高效工作學習方法 我們經常需要從各種不同類型的文檔中提取文本內容&#xff0c;無論是辦公文檔、圖像還是PDF文件。而Kreuzberg這個Python庫的出現&#xff0c;為我們提…

Windows程序設計29:對話框之間的數據傳遞

文章目錄 前言一、父子對話框之間的數據傳遞1.父窗口獲取子窗口數據2.子窗口獲取父窗口數據 二、類外函數調用窗口的操作1.全局變量方式2.參數傳遞方式 總結 前言 Windows程序設計29&#xff1a;對話框之間的數據傳遞。 在Windows程序設計28&#xff1a;MFC模態與非模態對話框…

【C語言】第八期——指針

目錄 1 初始指針 2 獲取變量的地址 3 定義指針變量、取地址、取值 3.1 定義指針變量 3.2 取地址、取值 4 對指針變量進行讀寫操作 5 指針變量作為函數參數 6 數組與指針 6.1 指針元素指向數組 6.2 指針加減運算&#xff08;了解&#xff09; 6.2.1 指針加減具體數字…

為 Power Automate 注冊 Adobe PDF Services

前言 最近&#xff0c;再測試如何將HTML轉換成PDF&#xff0c;然后發現Adobe有一個免費的操作可以用&#xff0c;好開心&#xff0c;趕緊注冊一下。 正文 1.先注冊一個賬號&#xff0c;然后登錄到Adobe Developer 注冊鏈接&#xff1a;https://www.adobe.com/go/getstarted_pow…

BY組態:工業自動化的未來,觸手可及

1. BY組態軟件的核心優勢 簡單易用&#xff1a;圖形化界面&#xff0c;降低學習成本&#xff0c;快速上手。 高效靈活&#xff1a;支持多種設備協議&#xff0c;兼容性強&#xff0c;適用于多種行業。 實時監控&#xff1a;提供實時數據采集與可視化&#xff0c;助力高效決策…

有哪些開源大數據處理項目使用了大模型

以下是一些使用了大模型的開源大數據處理項目&#xff1a; 1. **RedPajama**&#xff1a;這是一個開源項目&#xff0c;使用了LLM大語言模型數據處理組件&#xff0c;對GitHub代碼數據進行清洗和處理。具體流程包括數據清洗、過濾低質量樣本、識別和刪除重復樣本等步驟。 2. …

網絡安全之攻防筆記--通用安全漏洞SQL注入sqlmapOraclemongodbDB2

通用安全漏洞SQL注入&sqlmap&Oracle&mongodb&DB2 數據庫類型 ACCESS 特性 沒數據庫用戶 沒數據庫權限 沒數據庫查詢參數 沒有高權限注入說法 暴力猜解&#xff0c;借助字典得到數據 注入方式 聯合注入 偏移注入 表名列名猜解不到 偏移注入 MySQL 低權限 常…

【信息系統項目管理師-案例真題】2022下半年案例分析答案和詳解

更多內容請見: 備考信息系統項目管理師-專欄介紹和目錄 文章目錄 試題一(24分)【問題1】(6分)【問題2】(10分)【問題3】(8分)試題二(26分)【問題1】(8分)【問題2】(8分)【問題3】(4分)【問題4】(6分)試題三(25分)【問題1】(12分)【問題2】(7分)【問題…

正點原子[第三期]Arm(iMX6U)Linux系統移植和根文件系統構建-5.3 xxx_defconfig過程

前言&#xff1a; 本文是根據嗶哩嗶哩網站上“arm(iMX6U)Linux系統移植和根文件系統構鍵篇”視頻的學習筆記&#xff0c;在這里會記錄下正點原子 I.MX6ULL 開發板的配套視頻教程所作的實驗和學習筆記內容。本文大量引用了正點原子教學視頻和鏈接中的內容。 引用&#xff1a; …

C++初階——簡單實現list

目錄 1、前言 2、List.h 3、Test.cpp 1、前言 1. 簡單實現std::list&#xff0c;重點&#xff1a;迭代器&#xff0c;模板類&#xff0c;運算符重載。 2. 并不是&#xff0c;所有的類&#xff0c;都需要深拷貝&#xff0c;像迭代器類模板&#xff0c;只是用別的類的資源&am…

conda環境中運行“python --version“所得的版本與環境中的python版本不一致----deepseek并非全能

conda環境中運行python —version所得python版本與conda環境中的python版本不一致------deepseek并非全能 問題 conda環境中運行python —version所得python版本與conda環境中的python版本不一致 我所做的探索 1 網頁搜索 2 求助于DeepSeek 可以用四個字來形容deepseek給出…