随着 CPU 核心数的提升,单线程程序已无法充分发挥硬件性能。Java 提供了强大的并发编程支持,允许我们使用多线程来:
线程(Thread)是进程中的最小执行单元,一个进程可以包含多个线程,多个线程共享进程的资源。
📌 线程 VS 进程:
对比项 | 进程 | 线程 |
---|---|---|
定义 | 资源分配单位 | CPU 执行单位 |
资源 | 独立资源空间 | 共享资源(如堆) |
通信 | 开销大 | 更高效 |
开销 | 创建销毁开销大 | 开销较小 |
Thread
类java复制编辑public class MyThread extends Thread {
public void run() {
System.out.println("线程运行:" + Thread.currentThread().getName());
}
}
new MyThread().start();
Runnable
接口java复制编辑public class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable 线程执行");
}
}
new Thread(new MyRunnable()).start();
Callable
+ Future
java复制编辑Callable<String> task = () -> {
return "任务完成";
};
FutureTask<String> future = new FutureTask<>(task);
new Thread(future).start();
System.out.println(future.get());
📌 线程状态图如下:
sql复制编辑新建 NEW
↓
就绪 RUNNABLE ← 唤醒
↓
运行 RUNNING
↓ ↑
阻塞 BLOCKED/WAITING/TIMED_WAITING
↓
终止 TERMINATED
多个线程同时访问共享资源时,可能产生“竞态条件”:
java复制编辑class Counter {
int count = 0;
public void add() {
count++;
}
}
多个线程同时调用 add()
,可能导致最终 count
错误。
java复制编辑public synchronized void add() {
count++;
}
java复制编辑public void add() {
synchronized (this) {
count++;
}
}
java复制编辑public static synchronized void staticMethod() {}
📌 原理:
synchronized 会加锁对象的 monitor(监视器锁),底层依赖 JVM 实现。
java复制编辑public void deadlock() {
synchronized (resourceA) {
synchronized (resourceB) {
// 死锁风险
}
}
}
✅ 避免方式:
tryLock()
)
java复制编辑Lock lock = new ReentrantLock();
try {
lock.lock();
// 临界区
} finally {
lock.unlock();
}
📌 支持:
java复制编辑CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
new Thread(() -> {
// 执行任务
latch.countDown(); // 完成一次
}).start();
}
latch.await(); // 等待3个线程执行完
java复制编辑CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("三线程到达,开始执行任务");
});
适合多个线程协作的场景,例如并行计算。
java复制编辑Semaphore semaphore = new Semaphore(3);
semaphore.acquire();
try {
// 执行任务
} finally {
semaphore.release();
}
控制访问资源的最大线程数,如连接池。
java复制编辑ExecutorService pool = Executors.newFixedThreadPool(5);
pool.execute(() -> {
System.out.println("线程池任务执行");
});
📌 常见线程池类型:
类型 | 特点 |
---|---|
newFixedThreadPool | 固定线程数,适合稳定负载 |
newCachedThreadPool | 自动扩容/回收线程,适合短任务 |
newSingleThreadPool | 单线程,适合顺序执行 |
newScheduledPool | 定时任务调度 |
java复制编辑ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, 10,
60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
📌 参数说明图解:
nginx复制编辑corePoolSize → 核心线程数
maximumPoolSize → 最大线程数
keepAliveTime → 空闲线程存活时间
workQueue → 任务队列
handler → 拒绝策略
类名 | 描述 |
---|---|
ConcurrentHashMap | 线程安全的 HashMap |
CopyOnWriteArrayList | 读多写少的线程安全列表 |
BlockingQueue | 支持阻塞的队列接口 |
java复制编辑volatile boolean running = true;
📌 保证线程间变量的 可见性,但不保证原子性。
AtomicInteger
java复制编辑AtomicInteger counter = new AtomicInteger();
counter.incrementAndGet(); // 原子自增
基于 CAS(Compare and Swap)机制实现无锁并发。
问题 | 说明 |
---|---|
竞态条件 | 多线程抢占资源导致结果异常 |
死锁 | 线程互相等待资源,永不释放 |
饥饿 | 某线程长期得不到资源 |
活锁 | 不停改变状态但无法前进 |
jstack
: 查看线程堆栈
VisualVM
: 图形化分析工具
Java Flight Recorder
: Java 性能监控
java复制编辑class Bank {
private int balance = 1000;
public synchronized void withdraw(int amount) {
if (balance >= amount) {
try { Thread.sleep(100); } catch (Exception e) {}
balance -= amount;
System.out.println(Thread.currentThread().getName() + " 取款成功,剩余:" + balance);
} else {
System.out.println(Thread.currentThread().getName() + " 余额不足");
}
}
}
java复制编辑public class Test {
public static void main(String[] args) {
Bank bank = new Bank();
Runnable r = () -> bank.withdraw(800);
new Thread(r, "用户A").start();
new Thread(r, "用户B").start();
}
}
📌 观察输出结果并测试同步效果。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。