Java线程基础实战

CPU核数

查看代码
# CPU核数指CPU的物理核心数量,每个核心可独立执行指令。
# CPU核数就像工厂里的工人数量。每个核心就是一个独立的工人,能够同时处理不同的任务。现代CPU通常有2-16个核心,高端服务器可能有几十个核心。

# 核心越多,CPU并行处理任务的能力越强。例如,4核CPU可同时处理4个独立任务。
# Core(s) per socket(每插槽核心数)和Socket(s)(插槽数,总核数=核心数×插槽数)

[root@hadoop ~]# lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
Thread(s) per core:    1
Core(s) per socket:    8
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 158
Model name:            Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
Stepping:              13
CPU MHz:               800.024
CPU max MHz:           4900.0000
CPU min MHz:           800.0000
BogoMIPS:              7200.00
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              12288K
NUMA node0 CPU(s):     0-7
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch invpcid_single ssbd rsb_ctxsw ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear spec_ctrl intel_stibp flush_l1d arch_capabilities

线程

查看代码

/**
* 1. 线程是CPU核心通过超线程技术(Hyper-Threading)模拟的逻辑执行单元。一个物理核心可支持多个线程(通常2个)。
*    超线程允许核心在等待I/O或内存时切换到另一线程,提高资源利用率,但不等同于额外物理核心。
*
* 2. 线程有两个层面的含义:
*    2.1 硬件线程:现代CPU支持超线程技术,一个物理核心可以同时处理2个线程,就像一个熟练工人可以同时用左右手做不同的工作。
*    2.2 软件线程:程序中创建的执行单元,就像给工人分配的具体任务。
* 
* 3. 总逻辑核心数=核数×每核心线程数
*    核数__Core(s) per socket:lscpu | grep "Core(s)"
*    每核心线程数__Thread(s) per core: lscpu | grep "Core(s) per socket"
* 
* 4. 应用场景(注意:过多线程导致切换开销,过少线程浪费核心资源。)
*    CPU密集型(如计算):线程数≈核数,避免上下文切换
*    I/O密集型(如网络请求):线程数可为2×核数,利用等待时间。
*    4.1 Tomcat服务器:<Executor name="tomcatThreadPool" maxThreads="2×核数" />
*    4.2 批处理任务:
*        // 对象字段排序
*        List<Person> sorted = people.parallelStream()
*                                    .sorted(Comparator.comparing(Person::getAge))
*                                    .collect(Collectors.toList());
*    4.3 部署优化:
*        Docker限制CPU:docker run --cpus="4" myAppliccation
*        JVM参数优化: java -Xmx2g -XX:+UseParallelGC -jar Test.jar
*    4.4 性能监控:
*        使用htop或Java VisualVM监控线程与CPU使用
*        检查top -H输出,定位高CPU线程
*         
**/

public class Test {
    public static void main(String[] args) {
        // 逻辑核心数
        System.out.println(Runtime.getRuntime().availableProcessors());
    }
} 

创建线程方法

继承线程类 java.lang.Thread
实现接口 java.lang.Runnable、java.lang.Callable、java.lang.FutureTask
线程池

java.util.concurrent.ThreadPoolExecutor

  • Java线程池是预先创建并管理一组工作线程的机制,通过复用线程来避免频繁创建和销毁线程的开销
  • 线程池核心组件
    • corePoolSize:线程池中的常驻核心线程数
    • maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1
    • keepAliveTime:余的空闲线程的存活时间。 当线程池(中线程)数量超过corePoolSize时,且空闲时间达到keepAliveTime值时,多余空闲线程会被销毁直到剩下coolPoolSize个线程为止
    • unit:keepAliveTime的单位
    • workQueue:任务队列,被提交尚未被执行的任务
    • threadFactory:生成线程池中线程的线程工厂,用于创建线程(一般用默认的即可)
    • handler:拒绝策略,当任务队列满了且工作线程数大于等于线程池的最大线程数时,如何来拒绝请求执行的runnable的策略:
      • AbortPolicy(默认): 直接抛出java.util.concurrent.RejectedExecutionException,组织系统正常运行
      • CallerRunsPolicy:   调用者运行,不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量    
      • DiscardOldestPolicy: 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务;
      • DiscardPolicy: 直接丢弃任务,不予任何处理也不抛出异常(如果允许任务丢失,该方案适用)。
  • 线程池的工作原理:当提交新任务时,如果当前线程数少于核心线程数,直接创建新线程执行任务;如果核心线程都在忙碌,任务会被放入工作队列等待;当队列满了且线程数未达到最大值时,创建额外线程处理任务;如果所有线程都在工作且队列已满,则执行拒绝策略。

  • 线程池分类
    • FixedThreadPool:固定大小线程池,核心线程数等于最大线程数,使用无界
    • LinkedBlockingQueue:适合负载比较重的服务器环境,但可能因为队列无界导致内存溢出
    • CachedThreadPool:可缓存线程池,核心线程数为0,最大线程数为Integer.MAX_VALUE,使用SynchronousQueue。适合执行大量短期异步任务,但在高并发情况下可能创建过多线程
    • SingleThreadExecutor:单线程池,确保所有任务按照提交顺序串行执行。适合需要保证任务执行顺序的场景
    • ScheduledThreadPool:支持定时和周期性任务执行的线程池,基于DelayedWorkQueue实现

线程数量与CPU核数关系

CPU密集型:
特征:大量计算,很少等待
表现:CPU使用率高,内存/磁盘使用率低
例子:数学运算、图像处理、加密解密
线程策略:线程数 = CPU核数(避免上下文切换)

I/O密集型
特征:频繁等待,少量计算
表现:CPU使用率低,大量时间等待I/O
例子:文件读写、网络请求、数据库查询
线程策略:线程数 = CPU核数 × 2 至 CPU核数 × 4

 

实验

查看代码

查看代码
package org.asyncProgramming;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadPerformanceTest {

    public static void main(String[] args) {
        System.out.println(Runtime.getRuntime().availableProcessors());
        System.out.println("=== CPU密集型任务测试 ===");
        testCPUIntensiveTask();

        System.out.println("\n=== I/O密集型任务测试 ===");
        testIOIntensiveTask();

        System.out.println("\n=== 混合型任务测试 ===");
        testMixedTask();
    }

    // CPU密集型任务测试
    private static void testCPUIntensiveTask() {
        System.out.println("CPU密集型任务 - 计算密集运算");

        int[] threadCounts = {2, 4, 8, 16, 32, 64, 128, 256};
        int taskCount = 10000; // 固定任务数量

        for (int threadCount : threadCounts) {
            long startTime = System.currentTimeMillis();

            ExecutorService executor = Executors.newFixedThreadPool(threadCount);
            CountDownLatch latch = new CountDownLatch(taskCount);

            for (int i = 0; i < taskCount; i++) {
                final int taskId = i;
                executor.submit(() -> {
                    // CPU密集型计算:计算素数
                    int count = 0;
                    for (int num = 2; num <= 100000; num++) {
                        if (isPrime(num)) {
                            count++;
                        }
                    }
                    //  System.out.println("任务" + taskId + "完成,找到" + count + "个素数 [线程: " + Thread.currentThread().getName() + "]");
                    latch.countDown();
                });
            }

            try {
                latch.await();
                executor.shutdown();
                executor.awaitTermination(1, TimeUnit.MINUTES);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }

            long endTime = System.currentTimeMillis();
            System.out.println("线程数: " + threadCount + ", 耗时: " + (endTime - startTime) + "ms");
        }
    }

    // I/O密集型任务测试
    private static void testIOIntensiveTask() {
        System.out.println("I/O密集型任务 - 模拟网络请求");

        int[] threadCounts = {2, 4, 8, 16, 32, 64, 128, 256};
        int taskCount = 12; // 固定任务数量

        for (int threadCount : threadCounts) {
            long startTime = System.currentTimeMillis();

            ExecutorService executor = Executors.newFixedThreadPool(threadCount);
            CountDownLatch latch = new CountDownLatch(taskCount);

            for (int i = 0; i < taskCount; i++) {
                final int taskId = i;
                executor.submit(() -> {
                    try {
                        // 模拟I/O等待时间
                        Thread.sleep(1000);
                        //  System.out.println("任务" + taskId + "完成 [线程: " + Thread.currentThread().getName() + "]");
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    latch.countDown();
                });
            }

            try {
                latch.await();
                executor.shutdown();
                executor.awaitTermination(1, TimeUnit.MINUTES);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }

            long endTime = System.currentTimeMillis();
            System.out.println("线程数: " + threadCount + ", 耗时: " + (endTime - startTime) + "ms");
        }
    }

    // 混合型任务测试
    private static void testMixedTask() {
        System.out.println("混合型任务 - CPU计算 + I/O等待");

        int[] threadCounts = {2, 4, 8, 16, 32, 64, 128, 256};
        int taskCount = 8; // 固定任务数量

        for (int threadCount : threadCounts) {
            long startTime = System.currentTimeMillis();

            ExecutorService executor = Executors.newFixedThreadPool(threadCount);
            CountDownLatch latch = new CountDownLatch(taskCount);

            for (int i = 0; i < taskCount; i++) {
                final int taskId = i;
                executor.submit(() -> {
                    try {
                        // CPU计算部分
                        int count = 0;
                        for (int num = 2; num <= 10000; num++) {
                            if (isPrime(num)) {
                                count++;
                            }
                        }

                        // I/O等待部分
                        Thread.sleep(500);

                        //  System.out.println("任务" + taskId + "完成,找到" + count + "个素数 [线程: " + Thread.currentThread().getName() + "]");
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    latch.countDown();
                });
            }

            try {
                latch.await();
                executor.shutdown();
                executor.awaitTermination(1, TimeUnit.MINUTES);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }

            long endTime = System.currentTimeMillis();
            System.out.println("线程数: " + threadCount + ", 耗时: " + (endTime - startTime) + "ms");
        }
    }

    // 判断是否为素数的辅助方法
    private static boolean isPrime(int n) {
        if (n <= 1) return false;
        if (n <= 3) return true;
        if (n % 2 == 0 || n % 3 == 0) return false;

        for (int i = 5; i * i <= n; i += 6) {
            if (n % i == 0 || n % (i + 2) == 0) return false;
        }
        return true;
    }
}

实验结果

查看代码

查看代码
D:\opt\soft\dev\jdk\jdk-21.0.6\bin\java.exe -javaagent:D:\opt\soft\dev\idea\lib\idea_rt.jar=49211 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath D:\opt\workspace\java\HashConflict\target\classes org.asyncProgramming.ThreadPerformanceTest
16
=== CPU密集型任务测试 ===
CPU密集型任务 - 计算密集运算
线程数: 2, 耗时: 6032ms
线程数: 4, 耗时: 3148ms
线程数: 8, 耗时: 1867ms
线程数: 16, 耗时: 1415ms
线程数: 32, 耗时: 1460ms
线程数: 64, 耗时: 1412ms
线程数: 128, 耗时: 1426ms
线程数: 256, 耗时: 1430ms

=== I/O密集型任务测试 ===
I/O密集型任务 - 模拟网络请求
线程数: 2, 耗时: 6032ms
线程数: 4, 耗时: 3016ms
线程数: 8, 耗时: 2011ms
线程数: 16, 耗时: 1004ms
线程数: 32, 耗时: 1014ms
线程数: 64, 耗时: 1008ms
线程数: 128, 耗时: 1007ms
线程数: 256, 耗时: 1005ms

=== 混合型任务测试 ===
混合型任务 - CPU计算 + I/O等待
线程数: 2, 耗时: 2043ms
线程数: 4, 耗时: 1025ms
线程数: 8, 耗时: 513ms
线程数: 16, 耗时: 512ms
线程数: 32, 耗时: 511ms
线程数: 64, 耗时: 510ms
线程数: 128, 耗时: 511ms
线程数: 256, 耗时: 511ms

进程已结束,退出代码为 0

线程同步

为什么需要线程同步?

真实的业务痛点

查看代码

// 电商平台的秒杀场景:1000个用户同时抢购10件商品,如果没有合适的同步机制,就会出现如下危险的库存扣减代码
public class UnsafeInventory {
    private int stock = 10;
    
    public boolean purchase() {
        if (stock > 0) {          // 步骤1:检查库存 (问题:多个线程可能同时通过该步骤检查,导致库存被"超卖"。)
            // 模拟网络延迟
            Thread.sleep(10);
            stock--;              // 步骤2:扣减库存
            return true;
        }
        return false;
    }
}

并发问题的本质

  • 可见性:线程A修改了变量,线程B看不到
    • 使用volatile关键字;使用同步机制;使用并发工具类 
  • 原子性:操作被中断,导致数据不一致
    • 使用原子操作类;使用同步锁;使用CAS操作;  
  • 有序性:编译器重排序破坏了程序逻辑
    •   

基础同步机制

1. synchronized

public class SafeInventory {
    private int stock = 10;
    // 业务价值:确保库存扣减的原子性,彻底解决超卖问题。
    public synchronized boolean purchase() {
        if (stock > 0) {
            stock--;
            return true;
        }
        return false;
    }
}

// 优化:减小锁粒度,提高并发性能。
public class OptimizedOrderService {
    private final Object lockObj = new Object();
    private long sequence = 0;
    
    public String processOrder(Order order) {
        // 业务逻辑处理(不需要同步)
        validateOrder(order);
        calculatePrice(order);
        
        // 只对关键部分加锁
        synchronized (lockObj) {
            order.setOrderNumber(generateSequence());
            saveOrder(order);
        }
        
        // 后续处理(不需要同步)
        sendNotification(order);
        return order.getOrderNumber();
    }
}

2. volatile轻量级同步

// 业务场景:系统开关控制
public class SystemController {
    private volatile boolean maintenanceMode = false;
    
    // 业务请求处理
    public void handleRequest(Request request) {
        if (maintenanceMode) {
            throw new ServiceUnavailableException("系统维护中");
        }
        // 正常处理请求
        processRequest(request);
    }
    
    // 运维操作
    public void enableMaintenanceMode() {
        maintenanceMode = true;  // 立即对所有线程可见
    }
}
// 经典应用:双重检查锁单例
// 使用场景:状态标志变量;配置热更新;单例模式优化
public class ConfigManager {
    private static volatile ConfigManager instance;
    private Properties config;
    
    private ConfigManager() {
        // 加载配置文件
        loadConfig();
    }
    
    public static ConfigManager getInstance() {
        if (instance == null) {
            synchronized (ConfigManager.class) {
                if (instance == null) {
                    instance = new ConfigManager();
                }
            }
        }
        return instance;
    }
}

3. Lock接口:更灵活的同步机制

// 可中断锁:优雅处理超时
public class PaymentService {
    private final Lock paymentLock = new ReentrantLock();
    
    public boolean processPayment(PaymentRequest request) {
        try {
            // 尝试获取锁,最多等待3秒
            if (paymentLock.tryLock(3, TimeUnit.SECONDS)) {
                try {
                    return doPayment(request);
                } finally {
                    paymentLock.unlock();
                }
            } else {
                // 超时处理
                throw new PaymentTimeoutException("支付系统繁忙,请稍后重试");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
}
// 读写锁:读操作并发执行,写操作独占访问,显著提升读多写少场景的性能。
public class ProductCacheService {
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Map<String, Product> cache = new HashMap<>();
    
    // 高并发读操作
    public Product getProduct(String productId) {
        lock.readLock().lock();
        try {
            return cache.get(productId);
        } finally {
            lock.readLock().unlock();
        }
    }
    
    // 低频写操作
    public void updateProduct(Product product) {
        lock.writeLock().lock();
        try {
            cache.put(product.getId(), product);
            // 通知缓存更新
            notifyUpdateListeners(product);
        } finally {
            lock.writeLock().unlock();
        }
    }
}

 4. 线程同步工具类(CountDownLatch、Semaphore、CyclicBarrier)

// CountDownLatch:等待子任务完成
public class ReportGeneratorService {
    private final ExecutorService executor = Executors.newFixedThreadPool(5);
    
    public Report generateMonthlyReport(String month) {
        CountDownLatch latch = new CountDownLatch(4);
        
        // 并行生成报表的各个部分
        CompletableFuture<SalesData> salesFuture = CompletableFuture.supplyAsync(() -> {
            try {
                return generateSalesData(month);
            } finally {
                latch.countDown();
            }
        }, executor);
        
        CompletableFuture<UserData> userFuture = CompletableFuture.supplyAsync(() -> {
            try {
                return generateUserData(month);
            } finally {
                latch.countDown();
            }
        }, executor);
        
        // 等待所有子任务完成
        try {
            latch.await(30, TimeUnit.SECONDS);
            return new Report(salesFuture.get(), userFuture.get());
        } catch (Exception e) {
            throw new ReportGenerationException("报表生成失败", e);
        }
    }
}
// Semaphore:接口限流
public class ApiRateLimiter {
    private final Semaphore semaphore;
    
    public ApiRateLimiter(int maxConcurrentRequests) {
        this.semaphore = new Semaphore(maxConcurrentRequests);
    }
    
    public ApiResponse processRequest(ApiRequest request) {
        try {
            // 尝试获取许可证
            if (semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)) {
                try {
                    return handleRequest(request);
                } finally {
                    semaphore.release();
                }
            } else {
                return ApiResponse.rateLimited("请求过于频繁,请稍后重试");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return ApiResponse.error("请求被中断");
        }
    }
}
// CyclicBarrier:分阶段处理
public class BatchDataProcessor {
    private final CyclicBarrier barrier;
    private final int workerCount;
    
    public BatchDataProcessor(int workerCount) {
        this.workerCount = workerCount;
        this.barrier = new CyclicBarrier(workerCount, () -> {
            System.out.println("所有工作线程完成当前阶段,开始下一阶段");
        });
    }
    
    public void processData(List<DataRecord> records, int workerId) {
        try {
            // 第一阶段:数据清洗
            cleanData(records, workerId);
            barrier.await(); // 等待所有线程完成清洗
            
            // 第二阶段:数据转换
            transformData(records, workerId);
            barrier.await(); // 等待所有线程完成转换
            
            // 第三阶段:数据保存
            saveData(records, workerId);
            barrier.await(); // 等待所有线程完成保存
            
        } catch (Exception e) {
            throw new DataProcessingException("数据处理失败", e);
        }
    }
}

5. 原子操作类(AtomicInteger、AtomicBoolean、AtomicLong、AtomicReference)

// 网站访问统计
public class WebsiteAnalytics {
    private final AtomicLong totalPageViews = new AtomicLong(0);
    private final AtomicLong uniqueVisitors = new AtomicLong(0);
    private final ConcurrentHashMap<String, Boolean> visitedUsers = new ConcurrentHashMap<>();
    
    public void recordPageView(String userId) {
        // 总页面浏览量
        totalPageViews.incrementAndGet();
        
        // 独立访客统计
        if (visitedUsers.putIfAbsent(userId, true) == null) {
            uniqueVisitors.incrementAndGet();
        }
    }
    
    public AnalyticsData getAnalytics() {
        return new AnalyticsData(
            totalPageViews.get(),
            uniqueVisitors.get(),
            visitedUsers.size()
        );
    }
}
// 高性能计数器
public class PerformanceCounter {
    private final LongAdder successCount = new LongAdder();
    private final LongAdder failureCount = new LongAdder();
    private final LongAdder totalResponseTime = new LongAdder();
    
    public void recordSuccess(long responseTime) {
        successCount.increment();
        totalResponseTime.add(responseTime);
    }
    
    public void recordFailure() {
        failureCount.increment();
    }
    
    public PerformanceMetrics getMetrics() {
        long success = successCount.sum();
        long failure = failureCount.sum();
        long totalTime = totalResponseTime.sum();
        
        return new PerformanceMetrics(
            success,
            failure,
            success > 0 ? totalTime / success : 0  // 平均响应时间
        );
    }
}

性能优化和最佳实践

// 错误:锁粒度过大
public synchronized void badMethod() {
    doSomething();        // 不需要同步
    updateSharedData();   // 需要同步
    doSomethingElse();    // 不需要同步
}

// 正确:减小锁粒度
public void goodMethod() {
    doSomething();
    synchronized(this) {
        updateSharedData();   // 只同步必要部分
    }
    doSomethingElse();
}
import java.util.concurrent.TimeUnit;

/**
 * 死锁demo
 * 两个或两个以上的线程互相持有对方需要的锁,导致程序无法正常运行
 * 产生原因:同步代码块嵌套同步代码块
 * 排查方法:
 * <1> jps -l  // 查找出进程号
 * <2> jstack 进程号
 */
public class DeadLockDemo {
    public static void main(String[] args) {
        String obj1 = "AA";
        String obj2 = "BB";
        new Thread(new DeadLockResource(obj1, obj2), "AA").start();
        new Thread(new DeadLockResource(obj2, obj1), "BB").start();
    }
}

class DeadLockResource implements Runnable {

    private final String lockObj1;
    private final String lockObj2;

    public DeadLockResource(String lockObj1, String lockObj2) {
        this.lockObj1 = lockObj1;
        this.lockObj2 = lockObj2;
    }

    @Override
    public void run() {
        try {
            resource(lockObj1, lockObj2);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public static void resource(String lockA, String lockB) throws InterruptedException {
        synchronized (lockA) {
            System.out.println(Thread.currentThread().getName() + "\t获取" + lockA);
            TimeUnit.SECONDS.sleep(3);
            synchronized (lockB) {
                System.out.println(Thread.currentThread().getName() + "\t获取" + lockB);
            }
        }
    }

}

实际业务场景应用

public class DistributedLock {
    private final Lock localLock = new ReentrantLock();
    private final RedisTemplate redisTemplate;
    
    public boolean tryLock(String key, long timeout) {
        // 本地锁避免同一JVM内的竞争
        if (localLock.tryLock()) {
            try {
                // Redis分布式锁
                String lockValue = UUID.randomUUID().toString();
                Boolean result = redisTemplate.opsForValue()
                    .setIfAbsent(key, lockValue, timeout, TimeUnit.SECONDS);
                return Boolean.TRUE.equals(result);
            } finally {
                localLock.unlock();
            }
        }
        return false;
    }
}
public class CacheService {
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Map<String, Object> cache = new HashMap<>();
    private volatile boolean cacheValid = true;
    
    public Object getData(String key) {
        // 检查缓存是否有效
        if (!cacheValid) {
            refreshCache();
        }
        
        lock.readLock().lock();
        try {
            return cache.get(key);
        } finally {
            lock.readLock().unlock();
        }
    }
    
    private void refreshCache() {
        lock.writeLock().lock();
        try {
            if (!cacheValid) { // 双重检查
                loadDataFromDatabase();
                cacheValid = true;
            }
        } finally {
            lock.writeLock().unlock();
        }
    }
}
public class SecKillService {
    private final AtomicInteger stock = new AtomicInteger(100);
    private final Semaphore semaphore = new Semaphore(10); // 限制并发数
    
    public boolean secKill(String userId) {
        try {
            if (semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)) {
                try {
                    // 检查库存
                    int currentStock = stock.get();
                    if (currentStock > 0) {
                        // CAS更新库存
                        if (stock.compareAndSet(currentStock, currentStock - 1)) {
                            // 创建订单
                            createOrder(userId);
                            return true;
                        }
                    }
                    return false;
                } finally {
                    semaphore.release();
                }
            }
            return false;
        } catch (InterruptedException e) {
            return false;
        }
    }
}

 

小结

业务场景 推荐方案 原因
简单互斥 synchronized 语法简单,JVM优化
需要超时控制 ReentrantLock 支持tryLock
读多写少 ReadWriteLock 读操作并发
计数操作 AtomicInteger 无锁高性能
高并发计数 LongAdder 分段减少竞争
限流控制 Semaphore 控制并发数
等待完成 CountDownLatch 一次性同步

 

posted @ 2020-07-13 16:46  lvlin241  阅读(113)  评论(0)    收藏  举报