小熊奶糖(BearCandy)
小熊奶糖(BearCandy)
发布于 2025-10-15 / 0 阅读
0
0

Java线程详解笔记

Java线程详解笔记

1. 线程基本概念

1.1 什么是线程

  • 线程:程序执行流的最小单元,是进程中的一个实体
  • 进程 vs 线程
    • 进程:资源分配的基本单位,有独立的内存空间
    • 线程:CPU调度的基本单位,共享进程资源

1.2 线程状态

public enum State {
    NEW,           // 新建
    RUNNABLE,      // 可运行
    BLOCKED,       // 阻塞
    WAITING,       // 等待
    TIMED_WAITING, // 超时等待
    TERMINATED     // 终止
}

2. 创建线程的三种方式

2.1 继承Thread类

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程执行: " + Thread.currentThread().getName());
    }
}

// 使用
MyThread thread = new MyThread();
thread.start();  // 启动线程

2.2 实现Runnable接口

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程执行: " + Thread.currentThread().getName());
    }
}

// 使用
Thread thread = new Thread(new MyRunnable());
thread.start();

2.3 实现Callable接口

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        return "任务完成";
    }
}

// 使用
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new MyCallable());
String result = future.get(); // 获取返回值
executor.shutdown();

3. 线程常用方法

3.1 基本控制方法

// 线程控制
thread.start();        // 启动线程
thread.join();         // 等待线程结束
thread.join(1000);     // 最多等待1秒
thread.interrupt();    // 中断线程
Thread.sleep(1000);    // 睡眠1秒
Thread.yield();        // 让出CPU

// 获取线程信息
Thread.currentThread(); // 获取当前线程
thread.getName();      // 线程名称
thread.getId();        // 线程ID
thread.getPriority();  // 优先级(1-10)
thread.isAlive();      // 是否存活
thread.isInterrupted(); // 是否被中断

4. 线程同步

4.1 synchronized关键字

// 同步方法
public synchronized void syncMethod() {
    // 同步代码
}

// 同步代码块
public void someMethod() {
    synchronized(this) {  // 同步块
        // 需要同步的代码
    }
}

// 同步静态方法
public static synchronized void staticSyncMethod() {
    // 同步代码
}

4.2 Lock接口

public class Counter {
    private final Lock lock = new ReentrantLock();
    private int count = 0;
  
    public void increment() {
        lock.lock();  // 获取锁
        try {
            count++;
        } finally {
            lock.unlock();  // 释放锁
        }
    }
}

4.3 读写锁

public class ReadWriteCounter {
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    private int value = 0;
  
    public int getValue() {
        readLock.lock();
        try {
            return value;
        } finally {
            readLock.unlock();
        }
    }
  
    public void setValue(int value) {
        writeLock.lock();
        try {
            this.value = value;
        } finally {
            writeLock.unlock();
        }
    }
}

5. 线程通信

5.1 wait/notify机制

public class MessageQueue {
    private String message;
    private boolean empty = true;
  
    public synchronized String take() {
        while (empty) {
            try {
                wait();  // 等待消息
            } catch (InterruptedException e) {}
        }
        empty = true;
        notifyAll();  // 通知生产者
        return message;
    }
  
    public synchronized void put(String message) {
        while (!empty) {
            try {
                wait();  // 等待空间
            } catch (InterruptedException e) {}
        }
        empty = false;
        this.message = message;
        notifyAll();  // 通知消费者
    }
}

5.2 Condition条件

public class BoundedBuffer {
    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    private final Object[] items = new Object[100];
    private int putptr, takeptr, count;
  
    public void put(Object x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length)
                notFull.await();  // 等待不满
            items[putptr] = x;
            if (++putptr == items.length) putptr = 0;
            ++count;
            notEmpty.signal();  // 通知不空
        } finally {
            lock.unlock();
        }
    }
  
    public Object take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0)
                notEmpty.await();  // 等待不空
            Object x = items[takeptr];
            if (++takeptr == items.length) takeptr = 0;
            --count;
            notFull.signal();  // 通知不满
            return x;
        } finally {
            lock.unlock();
        }
    }
}

6. 线程池

6.1 创建线程池

// 固定大小线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(5);

// 缓存线程池
ExecutorService cachedPool = Executors.newCachedThreadPool();

// 单线程池
ExecutorService singleThread = Executors.newSingleThreadExecutor();

// 定时线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);

6.2 自定义线程池

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5,      // 核心线程数
    10,     // 最大线程数
    60L,    // 空闲线程存活时间
    TimeUnit.SECONDS,  // 时间单位
    new LinkedBlockingQueue<>(100),  // 工作队列
    Executors.defaultThreadFactory(), // 线程工厂
    new ThreadPoolExecutor.AbortPolicy()  // 拒绝策略
);

6.3 使用线程池

// 提交任务
Future<String> future = executor.submit(() -> {
    Thread.sleep(1000);
    return "任务结果";
});

// 执行任务
executor.execute(() -> {
    System.out.println("执行任务");
});

// 关闭线程池
executor.shutdown();        // 平缓关闭
executor.shutdownNow();     // 立即关闭

7. 并发工具类

7.1 CountDownLatch

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
      
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                System.out.println("子线程" + Thread.currentThread().getName() + "执行");
                latch.countDown();  // 计数减1
            }).start();
        }
      
        latch.await();  // 等待所有子线程执行完毕
        System.out.println("所有子线程执行完毕");
    }
}

7.2 CyclicBarrier

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3, () -> {
            System.out.println("所有线程到达屏障");
        });
      
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    System.out.println("线程" + Thread.currentThread().getName() + "到达屏障");
                    barrier.await();  // 等待其他线程
                    System.out.println("线程" + Thread.currentThread().getName() + "继续执行");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

7.3 Semaphore

public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);  // 允许3个线程同时访问
      
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();  // 获取许可
                    System.out.println("线程" + Thread.currentThread().getName() + "获得许可");
                    Thread.sleep(2000);
                    System.out.println("线程" + Thread.currentThread().getName() + "释放许可");
                    semaphore.release();  // 释放许可
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

7.4 Exchanger

public class ExchangerDemo {
    public static void main(String[] args) {
        Exchanger<String> exchanger = new Exchanger<>();
      
        new Thread(() -> {
            try {
                String data = "数据A";
                System.out.println("线程A发送: " + data);
                String received = exchanger.exchange(data);
                System.out.println("线程A收到: " + received);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
      
        new Thread(() -> {
            try {
                String data = "数据B";
                System.out.println("线程B发送: " + data);
                String received = exchanger.exchange(data);
                System.out.println("线程B收到: " + received);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

8. 原子操作类

8.1 基本类型原子类

AtomicInteger atomicInt = new AtomicInteger(0);
atomicInt.incrementAndGet();      // 原子自增
atomicInt.getAndIncrement();      // 获取后自增
atomicInt.addAndGet(5);           // 原子加5
atomicInt.compareAndSet(1, 2);    // CAS操作

AtomicBoolean atomicBool = new AtomicBoolean(true);
AtomicLong atomicLong = new AtomicLong(100L);

8.2 数组原子类

AtomicIntegerArray atomicArray = new AtomicIntegerArray(10);
atomicArray.set(0, 1);           // 设置值
atomicArray.getAndAdd(0, 5);     // 获取并相加

8.3 引用类型原子类

AtomicReference<String> atomicRef = new AtomicReference<>("初始值");
atomicRef.compareAndSet("初始值", "新值");

AtomicStampedReference<String> stampedRef = 
    new AtomicStampedReference<>("初始值", 0);
stampedRef.compareAndSet("初始值", "新值", 0, 1);

9. 线程安全集合

9.1 ConcurrentHashMap

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("key1", 1);
map.putIfAbsent("key1", 2);  // 如果不存在则添加
map.compute("key1", (k, v) -> v + 1);  // 计算新值

// 遍历
map.forEach((k, v) -> System.out.println(k + ": " + v));

9.2 CopyOnWriteArrayList

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("元素1");
list.addIfAbsent("元素1");  // 如果不存在则添加

// 遍历是线程安全的
for (String item : list) {
    System.out.println(item);
}

9.3 BlockingQueue

BlockingQueue<String> queue = new LinkedBlockingQueue<>(10);

// 生产者
queue.put("元素");  // 阻塞直到有空间

// 消费者
String element = queue.take();  // 阻塞直到有元素

10. 最佳实践和注意事项

10.1 线程安全设计原则

  1. 不可变对象:使用final字段
  2. 线程封闭:使用ThreadLocal
  3. 同步控制:合理使用锁
  4. 避免死锁:按顺序获取锁

10.2 性能考虑

  1. 减少锁的持有时间
  2. 减小锁的粒度
  3. 使用读写锁替代独占锁
  4. 考虑使用无锁编程

10.3 常见问题

  1. 死锁:多个线程互相等待对方释放锁
  2. 活锁:线程不断重试相同的操作
  3. 饥饿:线程长时间得不到执行机会
  4. 内存可见性:使用volatile或同步保证可见性

这份笔记涵盖了Java线程的核心概念和常用技术,可以作为学习和复习的参考资料。在实际开发中,要根据具体场景选择合适的线程技术和同步机制。


评论