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 线程安全设计原则
- 不可变对象:使用final字段
- 线程封闭:使用ThreadLocal
- 同步控制:合理使用锁
- 避免死锁:按顺序获取锁
10.2 性能考虑
- 减少锁的持有时间
- 减小锁的粒度
- 使用读写锁替代独占锁
- 考虑使用无锁编程
10.3 常见问题
- 死锁:多个线程互相等待对方释放锁
- 活锁:线程不断重试相同的操作
- 饥饿:线程长时间得不到执行机会
- 内存可见性:使用volatile或同步保证可见性
这份笔记涵盖了Java线程的核心概念和常用技术,可以作为学习和复习的参考资料。在实际开发中,要根据具体场景选择合适的线程技术和同步机制。