Java并发编程核心:线程基础知识

开篇

最近在学习GUI并发编程,本篇文章为相关整理的第1篇。

并发编程基础概念

  1. 并发 vs 并行
// 串行示例(顺序执行)
void makeTea() {
    washTeapot();   // 洗茶具
    fetchWater();   // 打水
    boilWater();    // 烧水
    pourTea();      // 冲茶
}

// 并行示例(多线程)
new Thread(() -> { washTeapot(); }).start();  // 并行洗茶具
new Thread(() -> { 
    fetchWater();
    boilWater();
    pourTea();
}).start();
  1. 并发编程价值
  • 资源利用率:多核CPU负载均衡
  • 响应速度:耗时任务异步处理(如Web服务器)
  • 任务拆分:分段下载/生产者消费者模型

线程安全的三大挑战

上下文切换开销

优化方案:

// 无锁编程示例(分段处理)
IntStream.range(0, 4).parallel().forEach(i -> {
    processSegment(data, i); // 每个线程处理不同数据段
});

// CAS原子操作
AtomicInteger count = new AtomicInteger();
count.incrementAndGet(); // 无锁线程安全

死锁(Deadlock)

经典死锁案例:

// HAIR_A 和 HAIR_B 两个锁对象
synchronized(HAIR_A) {
    Thread.sleep(50);
    synchronized(HAIR_B) { ... } // 等待B锁
}

synchronized(HAIR_B) {
    synchronized(HAIR_A) { ... } // 等待A锁
}

🔍 检测工具:jconsole 监控线程状态

线程不安全(Race Condition)

// 典型不安全操作
public class UnSafeThread {
    private static int num = 0;
    public static void inCreate() { num++; } // 非原子操作
    
    public static void main(String[] args) {
        // 10个线程各执行100次累加
        IntStream.range(0, 10).forEach(i -> new Thread(() -> {
            IntStream.range(0, 100).forEach(j -> inCreate());
        }).start());
        
        // 预期结果1000,实际输出<1000
    }
}

线程核心机制

线程生命周期

在这里插入图片描述

线程正确中断方式

// 推荐方案:状态标志位
class SafeInterrupt implements Runnable {
    private volatile boolean running = true;
    
    public void run() {
        while (running) {
            // 执行任务
        }
    }
    
    void cancel() { running = false; } // 安全终止
}

守护线程(Daemon Thread)

Thread daemonThread = new Thread(() -> {
    while (true) { /* 后台任务 */ }
});
daemonThread.setDaemon(true); // 设置为守护线程
daemonThread.start();

⚠️ 注意:JVM在所有用户线程结束时自动终止守护线程

线程安全实现方案

synchronized 同步锁

在这里插入图片描述

volatile 关键字

private volatile boolean flag; // 保证可见性

// 适用场景:状态标志位
public void shutdown() {
    flag = true; // 所有线程立即可见
}

💡 特点:可见性、禁止指令重排,但不保证原子性

原子类(Atomic Classes)

AtomicInteger counter = new AtomicInteger();

// 线程安全自增
counter.getAndIncrement(); 

// CAS底层实现
public final int getAndIncrement() {
    return U.getAndAddInt(this, VALUE, 1);
}

最佳实践总结

  1. 锁粒度控制:尽量缩小同步代码块范围
  2. 避免嵌套锁:预防死锁(Lock Ordering)
  3. 线程复用:使用线程池(ThreadPoolExecutor)
  4. 并发工具优先:ConcurrentHashMap > Collections.synchronizedMap()
  5. 状态不可变:final修饰共享变量

📊 性能对比:原子操作 > 无锁编程 > 轻量锁 > 重量锁
在这里插入图片描述

以上便是我本篇博客的所有内容了,感谢阅读!
希望您能有所收获~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值