<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Java并發(fā)編程基礎(chǔ):從線程管理到高并發(fā)應(yīng)用實(shí)踐

      本篇主要是多線程的基礎(chǔ)知識(shí),代碼示例較多,有時(shí)間的可以逐個(gè)分析,具體細(xì)節(jié)都放在代碼注釋中了。

      1. 理解線程:多任務(wù)執(zhí)行的基石

      1.1 什么是線程?

      在現(xiàn)代操作系統(tǒng)中,進(jìn)程是資源分配的基本單位,而線程是CPU調(diào)度的最小單位。可以把進(jìn)程想象成一家公司,線程就是公司里的員工。

      /**
       * 演示Java程序天生就是多線程程序
       * 即使最簡(jiǎn)單的main方法也會(huì)啟動(dòng)多個(gè)系統(tǒng)線程
       */
      public class MultiThread {
          public static void main(String[] args) {
              // 獲取Java線程管理MXBean
              ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
              // 不需要獲取同步的monitor和synchronizer信息,僅獲取線程和線程堆棧信息
              ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
              
              // 遍歷線程信息
              System.out.println("=== Java程序啟動(dòng)的線程列表 ===");
              for (ThreadInfo threadInfo : threadInfos) {
                  System.out.println("[" + threadInfo.getThreadId() + "] " + 
                                   threadInfo.getThreadName());
              }
          }
      }
      

      輸出示例:

      === Java程序啟動(dòng)的線程列表 ===
      [4] Signal Dispatcher    // 分發(fā)處理發(fā)送給JVM信號(hào)的線程
      [3] Finalizer           // 調(diào)用對(duì)象finalize方法的線程  
      [2] Reference Handler   // 清除Reference的線程
      [1] main               // main線程,用戶程序入口
      

      1.2 為什么需要多線程?

      三大核心優(yōu)勢(shì)

      1. 充分利用多核處理器 - 避免CPU資源閑置
      2. 提升響應(yīng)速度 - 后臺(tái)任務(wù)不阻塞用戶操作
      3. 更好的編程模型 - Java提供一致的多線程API

      1.3 線程狀態(tài)生命周期

      新建(NEW) → 可運(yùn)行(RUNNABLE) → 運(yùn)行中
          ↓
      超時(shí)等待(TIMED_WAITING) ← 等待(WAITING) ← 阻塞(BLOCKED)
          ↓
          終止(TERMINATED)
      

      2. 線程的啟動(dòng)與安全終止

      2.1 正確啟動(dòng)線程

      /**
       * 線程啟動(dòng)最佳實(shí)踐示例
       * 重點(diǎn):設(shè)置有意義的線程名稱,合理設(shè)置守護(hù)線程標(biāo)志
       */
      public class ThreadStartExample {
          public static void main(String[] args) {
              // 推薦:為線程設(shè)置有意義的名稱,便于問(wèn)題排查
              Thread worker = new Thread(new Task(), "Data-Processor-1");
              worker.setDaemon(false); // 明確設(shè)置是否為守護(hù)線程
              worker.start(); // 正確啟動(dòng)方式,不要直接調(diào)用run()
              
              System.out.println("主線程繼續(xù)執(zhí)行,不會(huì)等待worker線程");
          }
          
          static class Task implements Runnable {
              @Override
              public void run() {
                  System.out.println(Thread.currentThread().getName() + " 開(kāi)始執(zhí)行");
                  try {
                      // 模擬工作任務(wù)
                      Thread.sleep(1000);
                  } catch (InterruptedException e) {
                      System.out.println("任務(wù)被中斷");
                  }
                  System.out.println(Thread.currentThread().getName() + " 執(zhí)行完成");
              }
          }
      }
      

      2.2 安全終止線程的兩種方式

      方式一:使用中斷機(jī)制

      /**
       * 使用中斷機(jī)制安全終止線程
       * 重點(diǎn):理解中斷異常處理的最佳實(shí)踐
       */
      public class InterruptExample {
          public static void main(String[] args) throws InterruptedException {
              Thread worker = new Thread(new InterruptibleTask(), "Interruptible-Worker");
              worker.start();
              
              // 主線程等待2秒后中斷工作線程
              TimeUnit.SECONDS.sleep(2);
              System.out.println("主線程發(fā)送中斷信號(hào)");
              worker.interrupt(); // 發(fā)送中斷信號(hào)
              
              // 等待工作線程完全退出
              worker.join();
              System.out.println("工作線程已安全退出");
          }
          
          static class InterruptibleTask implements Runnable {
              @Override
              public void run() {
                  while (!Thread.currentThread().isInterrupted()) {
                      try {
                          // 模擬工作 - 這里可能拋出InterruptedException
                          System.out.println("Working...");
                          TimeUnit.MILLISECONDS.sleep(500);
                      } catch (InterruptedException e) {
                          /**
                           * 關(guān)鍵理解點(diǎn):為什么需要重新設(shè)置中斷狀態(tài)?
                           * 
                           * 當(dāng)線程在阻塞狀態(tài)(如sleep、wait、join)時(shí)被中斷,
                           * Java會(huì)做兩件事:
                           * 1. 拋出InterruptedException
                           * 2. 清除線程的中斷狀態(tài)(設(shè)為false)
                           * 
                           * 這導(dǎo)致循環(huán)條件 !Thread.currentThread().isInterrupted() 
                           * 會(huì)繼續(xù)為true,線程無(wú)法退出。
                           * 
                           * 因此我們需要在捕獲異常后重新設(shè)置中斷狀態(tài),
                           * 這樣循環(huán)條件就能檢測(cè)到中斷,安全退出。
                           */
                          System.out.println("捕獲到中斷異常,重新設(shè)置中斷狀態(tài)");
                          Thread.currentThread().interrupt(); // 重新設(shè)置中斷標(biāo)志
                      }
                  }
                  System.out.println("線程安全退出,中斷狀態(tài): " + 
                      Thread.currentThread().isInterrupted());
              }
          }
      }
      

      方式二:使用標(biāo)志位

      /**
       * 使用volatile標(biāo)志位安全終止線程
       * 適用于沒(méi)有阻塞調(diào)用或需要更復(fù)雜退出邏輯的場(chǎng)景
       */
      public class FlagShutdownExample {
          // volatile保證可見(jiàn)性,確保所有線程看到最新的值
          private volatile boolean running = true;
          private final Thread workerThread;
          
          public FlagShutdownExample() {
              this.workerThread = new Thread(this::doWork, "Flag-Controlled-Worker");
          }
          
          public void start() {
              workerThread.start();
          }
          
          /**
           * 優(yōu)雅停止工作線程
           */
          public void stop() {
              System.out.println("請(qǐng)求停止工作線程");
              running = false;
              // 同時(shí)發(fā)送中斷,處理可能存在的阻塞情況
              workerThread.interrupt();
          }
          
          /**
           * 工作線程的主循環(huán)
           * 同時(shí)檢查標(biāo)志位和中斷狀態(tài),提供雙重保障
           */
          private void doWork() {
              try {
                  while (running && !Thread.currentThread().isInterrupted()) {
                      // 執(zhí)行工作任務(wù)
                      processData();
                  }
              } finally {
                  // 無(wú)論何種方式退出,都執(zhí)行清理工作
                  cleanup();
              }
              System.out.println("工作線程已安全退出");
          }
          
          private void processData() {
              try {
                  // 模擬數(shù)據(jù)處理
                  System.out.println("處理數(shù)據(jù)中...");
                  Thread.sleep(300);
              } catch (InterruptedException e) {
                  System.out.println("處理數(shù)據(jù)時(shí)被中斷");
                  // 收到中斷,但可能還想繼續(xù)處理,所以不重新設(shè)置中斷
                  // 讓循環(huán)條件來(lái)檢查running標(biāo)志
              }
          }
          
          private void cleanup() {
              System.out.println("執(zhí)行資源清理工作...");
              // 關(guān)閉文件、數(shù)據(jù)庫(kù)連接等資源
          }
          
          public static void main(String[] args) throws InterruptedException {
              FlagShutdownExample example = new FlagShutdownExample();
              example.start();
              
              // 運(yùn)行3秒后停止
              Thread.sleep(3000);
              example.stop();
              
              // 等待工作線程退出
              example.workerThread.join();
          }
      }
      

      3. 線程間通信:協(xié)作的藝術(shù)

      3.1 volatile關(guān)鍵字:共享狀態(tài)可見(jiàn)性

      /**
       * volatile關(guān)鍵字示例
       * 保證多線程間的可見(jiàn)性,但不保證原子性
       */
      public class VolatileExample {
          // volatile確保shutdownRequested的修改對(duì)所有線程立即可見(jiàn)
          private volatile boolean shutdownRequested = false;
          private int operationCount = 0; // 非volatile,不保證可見(jiàn)性
          
          public void shutdown() {
              shutdownRequested = true; // 所有線程立即可見(jiàn)
              System.out.println("關(guān)閉請(qǐng)求已設(shè)置");
          }
          
          public void doWork() {
              while (!shutdownRequested) {
                  // 正常工作循環(huán)
                  operationCount++; // 非原子操作,可能有問(wèn)題
                  try {
                      Thread.sleep(100);
                  } catch (InterruptedException e) {
                      System.out.println("工作被中斷");
                      Thread.currentThread().interrupt();
                      break;
                  }
              }
              System.out.println("工作線程退出,操作次數(shù): " + operationCount);
          }
      }
      

      3.2 synchronized關(guān)鍵字:互斥訪問(wèn)

      /**
       * synchronized關(guān)鍵字示例
       * 保證原子性和可見(jiàn)性,但可能影響性能
       */
      public class SynchronizedCounter {
          private int count = 0;
          
          /**
           * 同步方法 - 鎖對(duì)象是當(dāng)前實(shí)例(this)
           */
          public synchronized void increment() {
              count++; // 原子操作
          }
          
          /**
           * 同步塊 - 可以更細(xì)粒度控制鎖的范圍
           */
          public void decrement() {
              // 只同步關(guān)鍵部分,減少鎖持有時(shí)間
              synchronized (this) {
                  count--;
              }
              // 這里可以執(zhí)行非同步操作
          }
          
          /**
           * 同步的get方法,保證看到最新值
           */
          public synchronized int getCount() {
              return count;
          }
          
          /**
           * 靜態(tài)同步方法 - 鎖對(duì)象是類的Class對(duì)象
           */
          public static synchronized void staticMethod() {
              // 靜態(tài)同步方法使用Class對(duì)象作為鎖
          }
      }
      

      3.3 等待/通知機(jī)制:經(jīng)典生產(chǎn)者-消費(fèi)者模式

      /**
       * 生產(chǎn)者-消費(fèi)者模式示例
       * 演示wait/notify機(jī)制的正確使用
       */
      public class WaitNotifyExample {
          private final Object lock = new Object(); // 共享鎖對(duì)象
          private final Queue<String> queue = new LinkedList<>();
          private final int MAX_SIZE = 5;
          
          /**
           * 生產(chǎn)者方法
           */
          public void produce(String data) throws InterruptedException {
              synchronized (lock) {
                  // 必須使用while循環(huán)檢查條件,避免虛假喚醒
                  while (queue.size() >= MAX_SIZE) {
                      System.out.println("隊(duì)列已滿(" + queue.size() + "),生產(chǎn)者等待");
                      lock.wait(); // 釋放鎖并等待
                  }
                  
                  queue.offer(data);
                  System.out.println("生產(chǎn): " + data + ",隊(duì)列大小: " + queue.size());
                  
                  // 通知所有等待的消費(fèi)者
                  lock.notifyAll();
              }
          }
          
          /**
           * 消費(fèi)者方法
           */
          public String consume() throws InterruptedException {
              synchronized (lock) {
                  // 必須使用while循環(huán)檢查條件
                  while (queue.isEmpty()) {
                      System.out.println("隊(duì)列為空,消費(fèi)者等待");
                      lock.wait(); // 釋放鎖并等待
                  }
                  
                  String data = queue.poll();
                  System.out.println("消費(fèi): " + data + ",隊(duì)列大小: " + queue.size());
                  
                  // 通知所有等待的生產(chǎn)者
                  lock.notifyAll();
                  return data;
              }
          }
          
          /**
           * 測(cè)試生產(chǎn)者消費(fèi)者模式
           */
          public static void main(String[] args) {
              WaitNotifyExample example = new WaitNotifyExample();
              
              // 啟動(dòng)生產(chǎn)者線程
              Thread producer = new Thread(() -> {
                  try {
                      for (int i = 0; i < 10; i++) {
                          example.produce("Data-" + i);
                          Thread.sleep(200);
                      }
                  } catch (InterruptedException e) {
                      Thread.currentThread().interrupt();
                  }
              }, "Producer");
              
              // 啟動(dòng)消費(fèi)者線程
              Thread consumer = new Thread(() -> {
                  try {
                      for (int i = 0; i < 10; i++) {
                          example.consume();
                          Thread.sleep(300);
                      }
                  } catch (InterruptedException e) {
                      Thread.currentThread().interrupt();
                  }
              }, "Consumer");
              
              producer.start();
              consumer.start();
          }
      }
      

      等待/通知經(jīng)典范式

      // 消費(fèi)者范式 - 永遠(yuǎn)在循環(huán)中調(diào)用wait()
      synchronized(鎖對(duì)象) {
          while(條件不滿足) {
              鎖對(duì)象.wait();  // 等待時(shí)會(huì)釋放鎖
          }
          // 條件滿足,處理業(yè)務(wù)邏輯
      }
      
      // 生產(chǎn)者范式  
      synchronized(鎖對(duì)象) {
          改變條件;           // 改變等待條件
          鎖對(duì)象.notifyAll(); // 通知所有等待線程
      }
      

      3.4 Thread.join():線程依賴執(zhí)行

      /**
       * Thread.join()使用示例
       * 實(shí)現(xiàn)線程間的順序執(zhí)行依賴
       */
      public class JoinExample {
          public static void main(String[] args) throws InterruptedException {
              System.out.println("主線程開(kāi)始");
              
              Thread previous = Thread.currentThread();
              
              // 創(chuàng)建5個(gè)有依賴關(guān)系的線程
              for (int i = 0; i < 5; i++) {
                  Thread thread = new Thread(new DependentTask(previous), "Worker-" + i);
                  thread.start();
                  previous = thread; // 設(shè)置依賴鏈
              }
              
              // 主線程先做一些工作
              TimeUnit.SECONDS.sleep(1);
              System.out.println(Thread.currentThread().getName() + " 完成初始化工作");
              
              // 等待所有線程完成(實(shí)際上由最后一個(gè)Worker-4 join主線程)
          }
          
          static class DependentTask implements Runnable {
              private final Thread dependency; // 依賴的線程
              
              public DependentTask(Thread dependency) {
                  this.dependency = dependency;
              }
              
              @Override
              public void run() {
                  try {
                      // 等待依賴的線程執(zhí)行完成
                      System.out.println(Thread.currentThread().getName() + " 等待 " + dependency.getName());
                      dependency.join();
                      
                      // 依賴線程完成后開(kāi)始自己的工作
                      System.out.println(Thread.currentThread().getName() + " 開(kāi)始工作");
                      TimeUnit.MILLISECONDS.sleep(500); // 模擬工作
                      System.out.println(Thread.currentThread().getName() + " 完成工作");
                      
                  } catch (InterruptedException e) {
                      System.out.println(Thread.currentThread().getName() + " 被中斷");
                      Thread.currentThread().interrupt();
                  }
              }
          }
      }
      

      3.5 ThreadLocal深入解析:線程局部變量

      /**
       * ThreadLocal深度解析
       * 理解原理、使用場(chǎng)景和內(nèi)存泄漏防護(hù)
       */
      public class ThreadLocalExample {
          
          /**
           * ThreadLocal基本使用:每個(gè)線程獨(dú)立的SimpleDateFormat
           * 避免SimpleDateFormat的線程安全問(wèn)題
           */
          private static final ThreadLocal<SimpleDateFormat> DATE_FORMATTER =
              ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
          
          /**
           * ThreadLocal用于用戶上下文傳遞
           * 在Web應(yīng)用中非常有用,避免在方法參數(shù)中傳遞用戶信息
           */
          private static final ThreadLocal<UserContext> USER_CONTEXT = 
              new ThreadLocal<>();
          
          /**
           * ThreadLocal用于事務(wù)上下文
           */
          private static final ThreadLocal<TransactionContext> TRANSACTION_CONTEXT =
              new ThreadLocal<>();
          
          /**
           * 可繼承的ThreadLocal:子線程可以繼承父線程的值
           */
          private static final InheritableThreadLocal<String> INHERITABLE_CONTEXT =
              new InheritableThreadLocal<>();
          
          /**
           * 處理用戶請(qǐng)求的示例方法
           */
          public void processRequest(User user) {
              // 設(shè)置用戶上下文到當(dāng)前線程
              USER_CONTEXT.set(new UserContext(user));
              
              try {
                  // 使用線程安全的日期格式化
                  String timestamp = DATE_FORMATTER.get().format(new Date());
                  System.out.println(Thread.currentThread().getName() + 
                      " - 用戶: " + user.getName() + ", 時(shí)間: " + timestamp);
                  
                  // 執(zhí)行業(yè)務(wù)邏輯 - 任何方法都可以獲取用戶上下文,無(wú)需傳遞參數(shù)
                  doBusinessLogic();
                  
              } finally {
                  /**
                   * 關(guān)鍵:必須清理ThreadLocal,防止內(nèi)存泄漏!
                   * 
                   * 原因:
                   * 1. ThreadLocalMap的key是弱引用,會(huì)被GC回收
                   * 2. 但value是強(qiáng)引用,不會(huì)被自動(dòng)回收
                   * 3. 如果線程長(zhǎng)時(shí)間存活(如線程池中的線程),會(huì)導(dǎo)致value無(wú)法釋放
                   * 4. 調(diào)用remove()方法顯式清理
                   */
                  USER_CONTEXT.remove();
                  DATE_FORMATTER.remove(); // 清理所有使用的ThreadLocal
              }
          }
          
          private void doBusinessLogic() {
              // 在任何地方都可以獲取用戶上下文,無(wú)需方法參數(shù)傳遞
              UserContext context = USER_CONTEXT.get();
              if (context != null) {
                  System.out.println("執(zhí)行業(yè)務(wù)邏輯,用戶: " + context.getUser().getName());
              }
              
              // 使用線程安全的日期格式化
              String now = DATE_FORMATTER.get().format(new Date());
              System.out.println("業(yè)務(wù)執(zhí)行時(shí)間: " + now);
          }
          
          /**
           * 演示ThreadLocal的內(nèi)存泄漏問(wèn)題
           */
          public void demonstrateMemoryLeak() {
              // 錯(cuò)誤的用法:不清理ThreadLocal
              ThreadLocal<byte[]> leakyLocal = new ThreadLocal<>();
              leakyLocal.set(new byte[1024 * 1024]); // 1MB數(shù)據(jù)
              
              // 如果沒(méi)有調(diào)用 leakyLocal.remove(), 即使leakyLocal=null,
              // 線程的ThreadLocalMap中仍然保留著這個(gè)Entry
              // 在線程池場(chǎng)景下,線程重用會(huì)導(dǎo)致內(nèi)存不斷增長(zhǎng)
          }
          
          /**
           * ThreadLocal最佳實(shí)踐:使用try-finally確保清理
           */
          public void bestPractice(User user) {
              USER_CONTEXT.set(new UserContext(user));
              try {
                  // 業(yè)務(wù)處理
                  doBusinessLogic();
              } finally {
                  // 確保清理,即使在業(yè)務(wù)邏輯中發(fā)生異常
                  USER_CONTEXT.remove();
              }
          }
          
          /**
           * 測(cè)試多線程環(huán)境下的ThreadLocal
           */
          public static void main(String[] args) throws InterruptedException {
              ThreadLocalExample example = new ThreadLocalExample();
              
              // 創(chuàng)建多個(gè)線程,每個(gè)線程有獨(dú)立的ThreadLocal值
              Thread[] threads = new Thread[3];
              for (int i = 0; i < threads.length; i++) {
                  final int userId = i;
                  threads[i] = new Thread(() -> {
                      User user = new User("User-" + userId);
                      example.processRequest(user);
                  }, "Thread-" + i);
                  
                  threads[i].start();
              }
              
              // 等待所有線程完成
              for (Thread thread : threads) {
                  thread.join();
              }
              
              System.out.println("所有線程執(zhí)行完成");
          }
          
          // 輔助類定義
          static class UserContext {
              private final User user;
              public UserContext(User user) { this.user = user; }
              public User getUser() { return user; }
          }
          
          static class User {
              private final String name;
              public User(String name) { this.name = name; }
              public String getName() { return name; }
          }
          
          static class TransactionContext {
              // 事務(wù)相關(guān)信息
          }
      }
      
      /**
       * ThreadLocal高級(jí)用法:自定義ThreadLocal子類
       */
      class AdvancedThreadLocal<T> extends ThreadLocal<T> {
          
          /**
           * 初始值 - 當(dāng)線程第一次調(diào)用get()時(shí),如果還沒(méi)有設(shè)置值,會(huì)調(diào)用此方法
           */
          @Override
          protected T initialValue() {
              System.out.println(Thread.currentThread().getName() + " - 初始化ThreadLocal值");
              return null; // 返回默認(rèn)初始值
          }
          
          /**
           * 子線程值繼承 - 僅對(duì)InheritableThreadLocal有效
           * 當(dāng)創(chuàng)建新線程時(shí),可以控制如何從父線程繼承值
           */
          protected T childValue(T parentValue) {
              System.out.println("子線程繼承父線程的值: " + parentValue);
              return parentValue; // 直接繼承,也可以進(jìn)行轉(zhuǎn)換
          }
      }
      

      4. 線程應(yīng)用實(shí)例:從理論到實(shí)踐

      4.1 等待超時(shí)模式:避免無(wú)限期等待

      /**
       * 等待超時(shí)模式實(shí)現(xiàn)
       * 在等待/通知機(jī)制基礎(chǔ)上增加超時(shí)控制
       */
      public class TimeoutWait<T> {
          private T result;
          
          /**
           * 帶超時(shí)的獲取方法
           * @param timeoutMs 超時(shí)時(shí)間(毫秒)
           * @return 結(jié)果,超時(shí)返回null
           */
          public synchronized T get(long timeoutMs) throws InterruptedException {
              long endTime = System.currentTimeMillis() + timeoutMs;
              long remaining = timeoutMs;
              
              // 循環(huán)檢查條件和剩余時(shí)間
              while (result == null && remaining > 0) {
                  wait(remaining); // 等待剩余時(shí)間
                  remaining = endTime - System.currentTimeMillis(); // 更新剩余時(shí)間
              }
              
              return result; // 可能為null(超時(shí))
          }
          
          /**
           * 設(shè)置結(jié)果并通知所有等待線程
           */
          public synchronized void set(T value) {
              this.result = value;
              notifyAll(); // 通知所有等待的線程
          }
          
          /**
           * 演示超時(shí)等待的使用
           */
          public static void main(String[] args) throws InterruptedException {
              TimeoutWait<String> waitObject = new TimeoutWait<>();
              
              // 消費(fèi)者線程 - 等待結(jié)果,最多等3秒
              Thread consumer = new Thread(() -> {
                  try {
                      System.out.println("消費(fèi)者開(kāi)始等待結(jié)果...");
                      String result = waitObject.get(3000);
                      if (result != null) {
                          System.out.println("消費(fèi)者收到結(jié)果: " + result);
                      } else {
                          System.out.println("消費(fèi)者等待超時(shí)");
                      }
                  } catch (InterruptedException e) {
                      System.out.println("消費(fèi)者被中斷");
                  }
              });
              
              // 生產(chǎn)者線程 - 2秒后產(chǎn)生結(jié)果
              Thread producer = new Thread(() -> {
                  try {
                      Thread.sleep(2000); // 模擬生產(chǎn)耗時(shí)
                      waitObject.set("生產(chǎn)完成的數(shù)據(jù)");
                      System.out.println("生產(chǎn)者完成工作");
                  } catch (InterruptedException e) {
                      System.out.println("生產(chǎn)者被中斷");
                  }
              });
              
              consumer.start();
              producer.start();
              
              consumer.join();
              producer.join();
          }
      }
      

      4.2 數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)

      /**
       * 簡(jiǎn)易數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)
       * 演示資源池化和等待超時(shí)模式的實(shí)際應(yīng)用
       */
      public class SimpleConnectionPool {
          private final LinkedList<Connection> pool = new LinkedList<>();
          private final int maxSize;
          private int createdCount = 0;
          
          public SimpleConnectionPool(int initialSize, int maxSize) {
              this.maxSize = maxSize;
              // 初始化連接池
              for (int i = 0; i < initialSize; i++) {
                  pool.add(createConnection());
              }
              System.out.println("連接池初始化完成,初始連接數(shù): " + initialSize);
          }
          
          /**
           * 獲取連接,支持超時(shí)
           */
          public Connection getConnection(long timeoutMs) throws InterruptedException, TimeoutException {
              synchronized (pool) {
                  // 如果池中有可用連接,立即返回
                  if (!pool.isEmpty()) {
                      return pool.removeFirst();
                  }
                  
                  // 池為空,但還可以創(chuàng)建新連接
                  if (createdCount < maxSize) {
                      Connection conn = createConnection();
                      System.out.println("創(chuàng)建新連接,當(dāng)前連接數(shù): " + createdCount);
                      return conn;
                  }
                  
                  // 等待可用連接
                  long endTime = System.currentTimeMillis() + timeoutMs;
                  long remaining = timeoutMs;
                  
                  while (pool.isEmpty() && remaining > 0) {
                      System.out.println(Thread.currentThread().getName() + " 等待連接,剩余時(shí)間: " + remaining + "ms");
                      pool.wait(remaining);
                      remaining = endTime - System.currentTimeMillis();
                  }
                  
                  if (!pool.isEmpty()) {
                      return pool.removeFirst();
                  }
                  throw new TimeoutException("獲取連接超時(shí),等待 " + timeoutMs + "ms");
              }
          }
          
          /**
           * 歸還連接到池中
           */
          public void releaseConnection(Connection conn) {
              if (conn != null) {
                  synchronized (pool) {
                      if (pool.size() < maxSize) {
                          pool.addLast(conn);
                          pool.notifyAll(); // 通知等待的線程
                          System.out.println("連接已歸還,當(dāng)前池大小: " + pool.size());
                      } else {
                          // 連接數(shù)超過(guò)上限,關(guān)閉連接
                          closeConnection(conn);
                          createdCount--;
                          System.out.println("連接池已滿,關(guān)閉連接");
                      }
                  }
              }
          }
          
          /**
           * 創(chuàng)建新連接
           */
          private Connection createConnection() {
              createdCount++;
              // 這里應(yīng)該是真實(shí)的數(shù)據(jù)庫(kù)連接創(chuàng)建邏輯
              System.out.println("創(chuàng)建第 " + createdCount + " 個(gè)連接");
              return new MockConnection();
          }
          
          /**
           * 關(guān)閉連接
           */
          private void closeConnection(Connection conn) {
              try {
                  conn.close();
              } catch (Exception e) {
                  System.err.println("關(guān)閉連接失敗: " + e.getMessage());
              }
          }
          
          /**
           * 獲取連接池狀態(tài)
           */
          public synchronized void printStatus() {
              System.out.println("連接池狀態(tài) - 池中連接: " + pool.size() + 
                                ", 總創(chuàng)建數(shù): " + createdCount + 
                                ", 最大限制: " + maxSize);
          }
          
          // 模擬數(shù)據(jù)庫(kù)連接
          static class MockConnection implements Connection {
              private final String id = UUID.randomUUID().toString().substring(0, 8);
              
              @Override
              public void close() {
                  System.out.println("關(guān)閉連接: " + id);
              }
              
              @Override
              public String toString() {
                  return "MockConnection{" + "id='" + id + '\'' + '}';
              }
              
              // 其他Connection接口方法...
              @Override public void commit() {}
              @Override public void rollback() {}
              // ... 簡(jiǎn)化實(shí)現(xiàn)
          }
          
          static class TimeoutException extends Exception {
              public TimeoutException(String message) { super(message); }
          }
      }
      

      4.3 線程池核心技術(shù)實(shí)現(xiàn)

      /**
       * 簡(jiǎn)易線程池實(shí)現(xiàn)
       * 理解線程池的核心原理和工作機(jī)制
       */
      public class SimpleThreadPool implements Executor {
          private final BlockingQueue<Runnable> workQueue;
          private final List<WorkerThread> workers;
          private volatile boolean isShutdown = false;
          private final int poolSize;
          
          /**
           * 創(chuàng)建線程池
           */
          public SimpleThreadPool(int poolSize) {
              this.poolSize = poolSize;
              this.workQueue = new LinkedBlockingQueue<>();
              this.workers = new ArrayList<>(poolSize);
              
              System.out.println("初始化線程池,大小: " + poolSize);
              
              // 創(chuàng)建工作線程
              for (int i = 0; i < poolSize; i++) {
                  WorkerThread worker = new WorkerThread("Pool-Worker-" + i);
                  workers.add(worker);
                  worker.start();
              }
          }
          
          /**
           * 提交任務(wù)到線程池
           */
          @Override
          public void execute(Runnable task) {
              if (isShutdown) {
                  throw new RejectedExecutionException("線程池已關(guān)閉,拒絕新任務(wù)");
              }
              
              if (task == null) {
                  throw new NullPointerException("任務(wù)不能為null");
              }
              
              try {
                  workQueue.put(task); // 阻塞直到有空間
                  System.out.println("任務(wù)已提交,隊(duì)列大小: " + workQueue.size());
              } catch (InterruptedException e) {
                  Thread.currentThread().interrupt();
                  throw new RejectedExecutionException("提交任務(wù)時(shí)被中斷", e);
              }
          }
          
          /**
           * 優(yōu)雅關(guān)閉線程池
           */
          public void shutdown() {
              System.out.println("開(kāi)始關(guān)閉線程池...");
              isShutdown = true;
              
              // 中斷所有工作線程
              for (WorkerThread worker : workers) {
                  worker.interrupt();
              }
          }
          
          /**
           * 強(qiáng)制關(guān)閉線程池
           */
          public void shutdownNow() {
              shutdown();
              workQueue.clear(); // 清空等待隊(duì)列
          }
          
          /**
           * 等待線程池完全終止
           */
          public boolean awaitTermination(long timeout, TimeUnit unit) 
                  throws InterruptedException {
              long endTime = System.currentTimeMillis() + unit.toMillis(timeout);
              
              for (WorkerThread worker : workers) {
                  long remaining = endTime - System.currentTimeMillis();
                  if (remaining <= 0) {
                      return false; // 超時(shí)
                  }
                  worker.join(remaining);
              }
              
              return true;
          }
          
          /**
           * 獲取線程池狀態(tài)
           */
          public void printStatus() {
              System.out.println("線程池狀態(tài) - 工作線程: " + workers.size() + 
                                ", 等待任務(wù): " + workQueue.size() + 
                                ", 已關(guān)閉: " + isShutdown);
          }
          
          /**
           * 工作線程實(shí)現(xiàn)
           */
          private class WorkerThread extends Thread {
              public WorkerThread(String name) {
                  super(name);
              }
              
              @Override
              public void run() {
                  System.out.println(getName() + " 開(kāi)始運(yùn)行");
                  
                  while (!isShutdown || !workQueue.isEmpty()) {
                      try {
                          // 從隊(duì)列獲取任務(wù),支持超時(shí)以便檢查關(guān)閉狀態(tài)
                          Runnable task = workQueue.poll(1, TimeUnit.SECONDS);
                          
                          if (task != null) {
                              System.out.println(getName() + " 開(kāi)始執(zhí)行任務(wù)");
                              task.run();
                              System.out.println(getName() + " 任務(wù)執(zhí)行完成");
                          }
                          
                      } catch (InterruptedException e) {
                          // 響應(yīng)中斷,退出線程
                          System.out.println(getName() + " 收到中斷信號(hào)");
                          break;
                      } catch (Exception e) {
                          // 捕獲任務(wù)執(zhí)行異常,避免工作線程退出
                          System.err.println(getName() + " 任務(wù)執(zhí)行異常: " + e.getMessage());
                      }
                  }
                  
                  System.out.println(getName() + " 退出");
              }
          }
          
          /**
           * 測(cè)試線程池
           */
          public static void main(String[] args) throws InterruptedException {
              SimpleThreadPool pool = new SimpleThreadPool(3);
              
              // 提交10個(gè)任務(wù)
              for (int i = 0; i < 10; i++) {
                  final int taskId = i;
                  pool.execute(() -> {
                      System.out.println(Thread.currentThread().getName() + 
                          " 執(zhí)行任務(wù) " + taskId);
                      try {
                          Thread.sleep(1000); // 模擬任務(wù)執(zhí)行
                      } catch (InterruptedException e) {
                          Thread.currentThread().interrupt();
                      }
                  });
              }
              
              // 查看狀態(tài)
              pool.printStatus();
              
              // 等待任務(wù)執(zhí)行
              Thread.sleep(5000);
              
              // 關(guān)閉線程池
              pool.shutdown();
              if (pool.awaitTermination(3, TimeUnit.SECONDS)) {
                  System.out.println("線程池已完全關(guān)閉");
              } else {
                  System.out.println("線程池關(guān)閉超時(shí),強(qiáng)制關(guān)閉");
                  pool.shutdownNow();
              }
          }
      }
      

      4.4 基于線程池的Web服務(wù)器

      /**
       * 基于線程池的簡(jiǎn)易Web服務(wù)器
       * 演示線程池在實(shí)際項(xiàng)目中的應(yīng)用
       */
      public class SimpleHttpServer {
          private final ExecutorService threadPool;
          private final ServerSocket serverSocket;
          private final String basePath;
          private volatile boolean isRunning = false;
          
          /**
           * 創(chuàng)建HTTP服務(wù)器
           */
          public SimpleHttpServer(int port, int poolSize, String basePath) throws IOException {
              this.threadPool = Executors.newFixedThreadPool(poolSize);
              this.serverSocket = new ServerSocket(port);
              this.basePath = basePath;
              
              // 確保基礎(chǔ)路徑存在
              File baseDir = new File(basePath);
              if (!baseDir.exists() || !baseDir.isDirectory()) {
                  throw new IllegalArgumentException("基礎(chǔ)路徑不存在或不是目錄: " + basePath);
              }
          }
          
          /**
           * 啟動(dòng)服務(wù)器
           */
          public void start() {
              if (isRunning) {
                  throw new IllegalStateException("服務(wù)器已經(jīng)在運(yùn)行");
              }
              
              isRunning = true;
              System.out.println("HTTP服務(wù)器啟動(dòng),端口: " + serverSocket.getLocalPort() + 
                                ", 基礎(chǔ)路徑: " + basePath);
              
              // 主接受循環(huán)
              Thread acceptorThread = new Thread(this::acceptConnections, "Server-Acceptor");
              acceptorThread.setDaemon(false);
              acceptorThread.start();
          }
          
          /**
           * 接受客戶端連接
           */
          private void acceptConnections() {
              while (isRunning) {
                  try {
                      Socket clientSocket = serverSocket.accept();
                      System.out.println("接受客戶端連接: " + 
                          clientSocket.getInetAddress().getHostAddress());
                      
                      // 提交到線程池處理
                      threadPool.execute(new HttpHandler(clientSocket, basePath));
                      
                  } catch (IOException e) {
                      if (isRunning) {
                          System.err.println("接受連接錯(cuò)誤: " + e.getMessage());
                      }
                      // 服務(wù)器關(guān)閉時(shí)的異常是正常的
                  }
              }
              System.out.println("服務(wù)器停止接受新連接");
          }
          
          /**
           * 停止服務(wù)器
           */
          public void stop() {
              System.out.println("正在停止服務(wù)器...");
              isRunning = false;
              
              try {
                  serverSocket.close();
              } catch (IOException e) {
                  System.err.println("關(guān)閉ServerSocket錯(cuò)誤: " + e.getMessage());
              }
              
              // 優(yōu)雅關(guān)閉線程池
              threadPool.shutdown();
              try {
                  if (!threadPool.awaitTermination(5, TimeUnit.SECONDS)) {
                      System.out.println("強(qiáng)制關(guān)閉線程池");
                      threadPool.shutdownNow();
                  }
              } catch (InterruptedException e) {
                  threadPool.shutdownNow();
                  Thread.currentThread().interrupt();
              }
              
              System.out.println("服務(wù)器已停止");
          }
          
          /**
           * HTTP請(qǐng)求處理器
           */
          private static class HttpHandler implements Runnable {
              private final Socket socket;
              private final String basePath;
              
              public HttpHandler(Socket socket, String basePath) {
                  this.socket = socket;
                  this.basePath = basePath;
              }
              
              @Override
              public void run() {
                  // 使用ThreadLocal記錄請(qǐng)求上下文
                  ThreadLocal<String> requestId = ThreadLocal.withInitial(
                      () -> UUID.randomUUID().toString().substring(0, 8)
                  );
                  
                  try (BufferedReader in = new BufferedReader(
                          new InputStreamReader(socket.getInputStream()));
                       PrintWriter out = new PrintWriter(socket.getOutputStream())) {
                      
                      String requestIdValue = requestId.get();
                      System.out.println("[" + requestIdValue + "] 開(kāi)始處理請(qǐng)求");
                      
                      // 解析HTTP請(qǐng)求
                      String requestLine = in.readLine();
                      if (requestLine == null || requestLine.isEmpty()) {
                          sendError(out, 400, "Bad Request");
                          return;
                      }
                      
                      String[] parts = requestLine.split(" ");
                      if (parts.length < 2) {
                          sendError(out, 400, "Bad Request");
                          return;
                      }
                      
                      String method = parts[0];
                      String path = parts[1];
                      
                      System.out.println("[" + requestIdValue + "] " + method + " " + path);
                      
                      // 只處理GET請(qǐng)求
                      if (!"GET".equals(method)) {
                          sendError(out, 405, "Method Not Allowed");
                          return;
                      }
                      
                      // 處理請(qǐng)求路徑
                      handleRequest(path, out, requestIdValue);
                      
                  } catch (IOException e) {
                      System.err.println("處理請(qǐng)求IO錯(cuò)誤: " + e.getMessage());
                  } finally {
                      // 清理ThreadLocal
                      requestId.remove();
                      
                      try {
                          socket.close();
                      } catch (IOException e) {
                          // 忽略關(guān)閉異常
                      }
                  }
              }
              
              private void handleRequest(String path, PrintWriter out, String requestId) {
                  try {
                      // 簡(jiǎn)單路徑安全校驗(yàn)
                      if (path.contains("..")) {
                          sendError(out, 403, "Forbidden");
                          return;
                      }
                      
                      // 默認(rèn)頁(yè)面
                      if ("/".equals(path)) {
                          path = "/index.html";
                      }
                      
                      File file = new File(basePath + path);
                      
                      // 文件不存在
                      if (!file.exists() || !file.isFile()) {
                          sendError(out, 404, "Not Found");
                          return;
                      }
                      
                      // 安全檢查:確保文件在基礎(chǔ)路徑內(nèi)
                      if (!file.getCanonicalPath().startsWith(new File(basePath).getCanonicalPath())) {
                          sendError(out, 403, "Forbidden");
                          return;
                      }
                      
                      // 根據(jù)文件類型設(shè)置Content-Type
                      String contentType = getContentType(file.getName());
                      
                      // 讀取文件內(nèi)容
                      byte[] content = Files.readAllBytes(file.toPath());
                      
                      // 發(fā)送HTTP響應(yīng)
                      out.println("HTTP/1.1 200 OK");
                      out.println("Server: SimpleHttpServer");
                      out.println("Content-Type: " + contentType);
                      out.println("Content-Length: " + content.length);
                      out.println("Connection: close");
                      out.println(); // 空行分隔頭部和主體
                      out.flush();
                      
                      // 發(fā)送文件內(nèi)容
                      socket.getOutputStream().write(content);
                      socket.getOutputStream().flush();
                      
                      System.out.println("[" + requestId + "] 響應(yīng)發(fā)送完成,文件: " + file.getName());
                      
                  } catch (IOException e) {
                      System.err.println("[" + requestId + "] 處理請(qǐng)求錯(cuò)誤: " + e.getMessage());
                      sendError(out, 500, "Internal Server Error");
                  }
              }
              
              private String getContentType(String filename) {
                  if (filename.endsWith(".html") || filename.endsWith(".htm")) {
                      return "text/html; charset=UTF-8";
                  } else if (filename.endsWith(".css")) {
                      return "text/css";
                  } else if (filename.endsWith(".js")) {
                      return "application/javascript";
                  } else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {
                      return "image/jpeg";
                  } else if (filename.endsWith(".png")) {
                      return "image/png";
                  } else {
                      return "application/octet-stream";
                  }
              }
              
              private void sendError(PrintWriter out, int code, String message) {
                  out.println("HTTP/1.1 " + code + " " + message);
                  out.println("Content-Type: text/html");
                  out.println("Connection: close");
                  out.println();
                  out.println("<html><body><h1>" + code + " " + message + "</h1></body></html>");
                  out.flush();
              }
          }
          
          /**
           * 啟動(dòng)服務(wù)器示例
           */
          public static void main(String[] args) {
              try {
                  // 創(chuàng)建服務(wù)器,端口8080,線程池大小10,基礎(chǔ)路徑為當(dāng)前目錄
                  SimpleHttpServer server = new SimpleHttpServer(8080, 10, ".");
                  server.start();
                  
                  System.out.println("服務(wù)器已啟動(dòng),訪問(wèn) http://localhost:8080/");
                  System.out.println("按Enter鍵停止服務(wù)器...");
                  
                  // 等待用戶輸入停止服務(wù)器
                  System.in.read();
                  server.stop();
                  
              } catch (Exception e) {
                  System.err.println("服務(wù)器啟動(dòng)失敗: " + e.getMessage());
                  e.printStackTrace();
              }
          }
      }
      

      5. 性能優(yōu)化與最佳實(shí)踐

      5.1 線程池大小配置策略

      /**
       * 線程池配置策略
       * 根據(jù)任務(wù)類型合理配置線程池參數(shù)
       */
      public class ThreadPoolConfig {
          
          /**
           * CPU密集型任務(wù)配置
           * 特點(diǎn):大量計(jì)算,很少IO等待
           * 策略:線程數(shù) ≈ CPU核心數(shù),避免過(guò)多線程競(jìng)爭(zhēng)CPU
           */
          public static ExecutorService newCpuIntensivePool() {
              int coreCount = Runtime.getRuntime().availableProcessors();
              int threadCount = coreCount + 1; // +1 確保CPU不會(huì)空閑
              System.out.println("CPU密集型線程池: " + threadCount + " 線程");
              return Executors.newFixedThreadPool(threadCount);
          }
          
          /**
           * IO密集型任務(wù)配置
           * 特點(diǎn):大量等待(網(wǎng)絡(luò)、磁盤IO)
           * 策略:線程數(shù) ≈ CPU核心數(shù) * (1 + 等待時(shí)間/計(jì)算時(shí)間)
           */
          public static ExecutorService newIoIntensivePool() {
              int coreCount = Runtime.getRuntime().availableProcessors();
              int threadCount = coreCount * 2; // 經(jīng)驗(yàn)值,可根據(jù)實(shí)際情況調(diào)整
              System.out.println("IO密集型線程池: " + threadCount + " 線程");
              return Executors.newFixedThreadPool(threadCount);
          }
          
          /**
           * 混合型任務(wù)配置
           * 根據(jù)CPU和IO比例動(dòng)態(tài)調(diào)整
           */
          public static ExecutorService newMixedPool(double cpuRatio, double ioRatio) {
              int coreCount = Runtime.getRuntime().availableProcessors();
              int threadCount = (int) (coreCount * cpuRatio + ioRatio);
              threadCount = Math.max(1, Math.min(threadCount, 100)); // 合理范圍限制
              System.out.println("混合型線程池: " + threadCount + " 線程");
              return Executors.newFixedThreadPool(threadCount);
          }
          
          /**
           * 自定義線程池 - 更精細(xì)的控制
           */
          public static ThreadPoolExecutor newCustomPool(int corePoolSize, 
                                                        int maxPoolSize,
                                                        long keepAliveTime,
                                                        int queueSize) {
              return new ThreadPoolExecutor(
                  corePoolSize,
                  maxPoolSize,
                  keepAliveTime,
                  TimeUnit.SECONDS,
                  new LinkedBlockingQueue<>(queueSize),
                  new CustomThreadFactory(),
                  new CustomRejectionPolicy()
              );
          }
          
          /**
           * 自定義線程工廠,設(shè)置更有意義的線程名稱
           */
          static class CustomThreadFactory implements ThreadFactory {
              private final AtomicInteger counter = new AtomicInteger(1);
              
              @Override
              public Thread newThread(Runnable r) {
                  Thread thread = new Thread(r, "CustomPool-Thread-" + counter.getAndIncrement());
                  thread.setDaemon(false);
                  thread.setPriority(Thread.NORM_PRIORITY);
                  return thread;
              }
          }
          
          /**
           * 自定義拒絕策略
           */
          static class CustomRejectionPolicy implements RejectedExecutionHandler {
              @Override
              public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                  System.err.println("任務(wù)被拒絕,當(dāng)前活躍線程: " + executor.getActiveCount() + 
                                   ", 隊(duì)列大小: " + executor.getQueue().size());
                  // 可以記錄日志、發(fā)送告警等
                  throw new RejectedExecutionException("線程池已滿,拒絕新任務(wù)");
              }
          }
      }
      

      5.2 避免常見(jiàn)陷阱

      1. 死鎖預(yù)防與檢測(cè)

      /**
       * 死鎖預(yù)防示例
       * 演示如何避免和檢測(cè)死鎖
       */
      public class DeadlockPrevention {
          
          /**
           * 死鎖產(chǎn)生示例 - 錯(cuò)誤的鎖順序
           */
          public static class DeadlockExample {
              private final Object lock1 = new Object();
              private final Object lock2 = new Object();
              
              public void method1() {
                  synchronized (lock1) {
                      System.out.println(Thread.currentThread().getName() + " 獲得 lock1");
                      try { Thread.sleep(100); } catch (InterruptedException e) {}
                      
                      synchronized (lock2) {  // 可能死鎖
                          System.out.println(Thread.currentThread().getName() + " 獲得 lock2");
                      }
                  }
              }
              
              public void method2() {
                  synchronized (lock2) {  // 不同的鎖順序
                      System.out.println(Thread.currentThread().getName() + " 獲得 lock2");
                      try { Thread.sleep(100); } catch (InterruptedException e) {}
                      
                      synchronized (lock1) {  // 可能死鎖
                          System.out.println(Thread.currentThread().getName() + " 獲得 lock1");
                      }
                  }
              }
          }
          
          /**
           * 死鎖預(yù)防 - 統(tǒng)一的鎖順序
           */
          public static class DeadlockPreventionExample {
              private final Object lock1 = new Object();
              private final Object lock2 = new Object();
              
              /**
               * 使用統(tǒng)一的鎖獲取順序來(lái)預(yù)防死鎖
               * 總是先獲取lock1,再獲取lock2
               */
              public void method1() {
                  synchronized (lock1) {
                      System.out.println(Thread.currentThread().getName() + " 獲得 lock1");
                      try { Thread.sleep(100); } catch (InterruptedException e) {}
                      
                      synchronized (lock2) {
                          System.out.println(Thread.currentThread().getName() + " 獲得 lock2");
                          // 業(yè)務(wù)邏輯
                      }
                  }
              }
              
              public void method2() {
                  synchronized (lock1) {  // 相同的鎖順序
                      System.out.println(Thread.currentThread().getName() + " 獲得 lock1");
                      try { Thread.sleep(100); } catch (InterruptedException e) {}
                      
                      synchronized (lock2) {
                          System.out.println(Thread.currentThread().getName() + " 獲得 lock2");
                          // 業(yè)務(wù)邏輯
                      }
                  }
              }
          }
          
          /**
           * 使用tryLock避免死鎖
           */
          public static class TryLockExample {
              private final Lock lock1 = new ReentrantLock();
              private final Lock lock2 = new ReentrantLock();
              
              public boolean tryDoWork() {
                  // 嘗試獲取第一個(gè)鎖
                  if (lock1.tryLock()) {
                      try {
                          System.out.println(Thread.currentThread().getName() + " 獲得 lock1");
                          
                          // 嘗試獲取第二個(gè)鎖
                          if (lock2.tryLock()) {
                              try {
                                  System.out.println(Thread.currentThread().getName() + " 獲得 lock2");
                                  // 執(zhí)行業(yè)務(wù)邏輯
                                  return true;
                              } finally {
                                  lock2.unlock();
                              }
                          }
                      } finally {
                          lock1.unlock();
                      }
                  }
                  return false; // 獲取鎖失敗
              }
          }
          
          /**
           * 死鎖檢測(cè)工具
           */
          public static void detectDeadlock() {
              ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
              long[] threadIds = threadBean.findDeadlockedThreads();
              
              if (threadIds != null) {
                  System.err.println("檢測(cè)到死鎖!");
                  ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds);
                  
                  for (ThreadInfo threadInfo : threadInfos) {
                      System.err.println("死鎖線程: " + threadInfo.getThreadName());
                      System.err.println("等待鎖: " + threadInfo.getLockName());
                      System.err.println("被線程持有: " + threadInfo.getLockOwnerName());
                  }
              } else {
                  System.out.println("未檢測(cè)到死鎖");
              }
          }
      }
      

      2. 資源清理最佳實(shí)踐

      /**
       * 資源清理最佳實(shí)踐
       * 演示如何正確管理和清理多線程資源
       */
      public class ResourceCleanup implements AutoCloseable {
          private final ExecutorService executor;
          private final List<AutoCloseable> resources;
          
          public ResourceCleanup(int threadPoolSize) {
              this.executor = Executors.newFixedThreadPool(threadPoolSize);
              this.resources = new ArrayList<>();
              System.out.println("資源管理器初始化完成,線程池大小: " + threadPoolSize);
          }
          
          /**
           * 提交任務(wù)
           */
          public <T> Future<T> submit(Callable<T> task) {
              return executor.submit(task);
          }
          
          /**
           * 注冊(cè)需要管理的資源
           */
          public void registerResource(AutoCloseable resource) {
              synchronized (resources) {
                  resources.add(resource);
              }
          }
          
          /**
           * 實(shí)現(xiàn)AutoCloseable,支持try-with-resources
           */
          @Override
          public void close() {
              System.out.println("開(kāi)始清理資源...");
              
              // 1. 關(guān)閉線程池
              shutdownExecutor();
              
              // 2. 關(guān)閉所有注冊(cè)的資源
              closeRegisteredResources();
              
              System.out.println("資源清理完成");
          }
          
          /**
           * 優(yōu)雅關(guān)閉線程池
           */
          private void shutdownExecutor() {
              executor.shutdown(); // 停止接受新任務(wù)
              try {
                  // 等待現(xiàn)有任務(wù)完成
                  if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                      System.out.println("線程池關(guān)閉超時(shí),嘗試強(qiáng)制關(guān)閉");
                      // 取消所有未開(kāi)始的任務(wù)
                      executor.shutdownNow();
                      
                      // 再次等待
                      if (!executor.awaitTermination(3, TimeUnit.SECONDS)) {
                          System.err.println("線程池?zé)o法完全關(guān)閉");
                      }
                  }
              } catch (InterruptedException e) {
                  // 重新中斷并強(qiáng)制關(guān)閉
                  executor.shutdownNow();
                  Thread.currentThread().interrupt();
              }
          }
          
          /**
           * 關(guān)閉所有注冊(cè)的資源
           */
          private void closeRegisteredResources() {
              synchronized (resources) {
                  for (AutoCloseable resource : resources) {
                      try {
                          resource.close();
                      } catch (Exception e) {
                          System.err.println("關(guān)閉資源時(shí)出錯(cuò): " + e.getMessage());
                          // 繼續(xù)關(guān)閉其他資源,不拋出異常
                      }
                  }
                  resources.clear();
              }
          }
          
          /**
           * 使用示例
           */
          public static void main(String[] args) {
              // 使用try-with-resources確保資源清理
              try (ResourceCleanup manager = new ResourceCleanup(3)) {
                  
                  // 注冊(cè)一些資源
                  manager.registerResource(() -> System.out.println("關(guān)閉數(shù)據(jù)庫(kù)連接"));
                  manager.registerResource(() -> System.out.println("關(guān)閉網(wǎng)絡(luò)連接"));
                  
                  // 提交任務(wù)
                  Future<String> future = manager.submit(() -> {
                      Thread.sleep(1000);
                      return "任務(wù)完成";
                  });
                  
                  // 獲取結(jié)果
                  String result = future.get();
                  System.out.println("任務(wù)結(jié)果: " + result);
                  
              } catch (Exception e) {
                  System.err.println("執(zhí)行出錯(cuò): " + e.getMessage());
              }
              // 這里會(huì)自動(dòng)調(diào)用close()方法清理資源
          }
      }
      

      6. 總結(jié)與核心要點(diǎn)

      6.1 關(guān)鍵知識(shí)點(diǎn)回顧

      1. 中斷異常處理的核心理解

      try {
          Thread.sleep(1000);
      } catch (InterruptedException e) {
          /**
           * 必須重新設(shè)置中斷狀態(tài)的原因:
           * 1. 當(dāng)阻塞方法拋出InterruptedException時(shí),會(huì)清除線程的中斷狀態(tài)
           * 2. 如果不重新設(shè)置,調(diào)用者無(wú)法知道線程曾被中斷
           * 3. 這破壞了中斷的傳播機(jī)制
           */
          Thread.currentThread().interrupt(); // 恢復(fù)中斷狀態(tài)
          // 或者直接拋出異常:throw new RuntimeException(e);
      }
      

      2. ThreadLocal內(nèi)存管理

      public void usingThreadLocal() {
          try {
              threadLocal.set(someValue);
              // 使用threadLocal
          } finally {
              /**
               * 必須清理ThreadLocal的原因:
               * 1. ThreadLocalMap使用弱引用作為key,但value是強(qiáng)引用
               * 2. 如果線程長(zhǎng)時(shí)間存活(線程池),value不會(huì)被GC回收
               * 3. 導(dǎo)致內(nèi)存泄漏,特別是存儲(chǔ)大對(duì)象時(shí)
               */
              threadLocal.remove(); // 必須調(diào)用!
          }
      }
      

      6.2 最佳實(shí)踐清單

      1. 線程命名:為所有線程設(shè)置有意義的名字
      2. 異常處理:在Runnable.run()中捕獲所有異常
      3. 資源清理:使用try-finally或try-with-resources
      4. 中斷響應(yīng):合理處理InterruptedException
      5. 鎖順序:統(tǒng)一鎖獲取順序避免死鎖
      6. 線程池:優(yōu)先使用線程池而非直接創(chuàng)建線程
      7. volatile:僅用于簡(jiǎn)單的狀態(tài)標(biāo)志
      8. ThreadLocal清理:使用后必須調(diào)用remove()

      6.3 性能調(diào)優(yōu)建議

      場(chǎng)景 推薦配置 說(shuō)明
      CPU密集型 線程數(shù) = CPU核心數(shù) + 1 減少線程切換開(kāi)銷
      IO密集型 線程數(shù) = CPU核心數(shù) × 2 充分利用等待時(shí)間
      混合型 根據(jù)監(jiān)控動(dòng)態(tài)調(diào)整 結(jié)合實(shí)際負(fù)載

      6.4 常見(jiàn)問(wèn)題排查

      1. 死鎖檢測(cè):使用jstack或ThreadMXBean
      2. 內(nèi)存泄漏:檢查ThreadLocal使用,特別是線程池場(chǎng)景
      3. CPU過(guò)高:檢查是否存在忙等待或過(guò)多線程競(jìng)爭(zhēng)
      4. 響應(yīng)慢:檢查鎖競(jìng)爭(zhēng)、IO阻塞或線程池配置

      掌握這些Java并發(fā)編程的基礎(chǔ)知識(shí)和最佳實(shí)踐,能夠幫助開(kāi)發(fā)者構(gòu)建出高性能、高可靠的多線程應(yīng)用程序。記住,并發(fā)編程的核心在于正確的同步、合理的資源管理和清晰的線程通信

      posted @ 2025-10-27 19:52  佛祖讓我來(lái)巡山  閱讀(153)  評(píng)論(1)    收藏  舉報(bào)

      佛祖讓我來(lái)巡山博客站 - 創(chuàng)建于 2018-08-15

      開(kāi)發(fā)工程師個(gè)人站,內(nèi)容主要是網(wǎng)站開(kāi)發(fā)方面的技術(shù)文章,大部分來(lái)自學(xué)習(xí)或工作,部分來(lái)源于網(wǎng)絡(luò),希望對(duì)大家有所幫助。

      Bootstrap中文網(wǎng)

      主站蜘蛛池模板: 精品国产第一国产综合精品| 国产欧美日韩亚洲一区二区三区| 蜜桃精品成人影片| www国产精品内射熟女| 精品亚洲无人区一区二区| 91超碰在线精品| 国产婷婷精品av在线| 亚洲乱妇老熟女爽到高潮的片| 国产高潮刺激叫喊视频| 亚洲中文字幕在线二页| 亚洲一级片一区二区三区| 中文字幕在线精品国产| 乱中年女人伦av二区| 国产福利视频区一区二区| 国产亚洲一区二区三区成人| 亚洲欧美成人a∨观看| 日本精品一区二区不卡| 91孕妇精品一区二区三区| 国产亚洲欧洲av综合一区二区三区| 香港日本三级亚洲三级| 热久在线免费观看视频| 无码专区 人妻系列 在线| 无码人妻精品一区二区三区免费| 亚洲人精品午夜射精日韩| 久久人人爽人人爽人人av| 国内精品卡一卡二卡三| 亚洲成人免费一级av| 久久精品国产蜜臀av| 男女啪啪永久免费观看网站| 久久热这里只有精品66| 黄色A级国产免费大片视频| 日本一区二区三区专线| 国产一区二区亚洲精品| 色爱综合另类图片av| 国产一区二区三区禁18| 国产成人精品一区二三区| 99riav精品免费视频观看| 国产不卡精品视频男人的天堂| 一区二区三区四区自拍视频| 日本伊人色综合网| 亚洲男人电影天堂无码|