// 方式1:继承Thread类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running by extending Thread");
}
}
// 方式2:实现Runnable接口(推荐,避免单继承限制,在Java中,类只能继承一个父类(单继承),但可以实现多个接口)
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Thread running by implementing Runnable");
}
}
public class Main {
public static void main(String[] args) {
new MyThread().start(); // 方式1 启动线程(调用start(),而非run()!直接调用run()只是普通方法调用,不会创建新线程)
new Thread(new MyRunnable()).start(); // 方式2
}
}
Runnable优势总结:
Runnable
表示任务逻辑,Thread
表示线程载体,符合面向对象的职责分离原则。Runnable
实例(例如售票系统的共享票池)。ExecutorService
)、Lambda表达式等现代特性无缝结合。start()
。start()
后,等待CPU调度。run()
方法。sleep()
等暂停执行。run()
执行完毕或发生未捕获异常。当多个线程同时访问共享资源且未正确同步时,结果依赖于线程执行顺序。
// 典型竞态条件示例:不安全的计数器
class UnsafeCounter {
private int count = 0;
public void increment() {
count++; // 非原子操作(实际为 read-modify-write)
}
public int getCount() { return count; }
}
this
)或类对象(静态方法)。class SafeCounter {
private int count = 0;
public synchronized void increment() {
count++;
}
// 等价同步代码块:
// public void increment() {
// synchronized(this) { count++; }
// }
}
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class SafeCounterWithLock {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock(); // 确保释放锁
}
}
}
volatile
变量的修改立即对其他线程可见。class VolatileExample {
private volatile boolean flag = false;
public void toggleFlag() {
flag = !flag; // 非原子操作,volatile仅保证可见性
}
}
wait()
:释放锁并进入等待状态。notify()
:随机唤醒一个等待线程。notifyAll()
:唤醒所有等待线程。import java.util.LinkedList;
import java.util.Queue;
class SharedBuffer {
private final Queue<Integer> queue = new LinkedList<>();
private final int capacity = 5;
// 生产者线程逻辑
public synchronized void produce(int item) throws InterruptedException {
while (queue.size() == capacity) {
wait(); // 缓冲区满,等待消费者消费
}
queue.add(item);
System.out.println("生产: " + item + ",当前队列大小: " + queue.size());
notifyAll(); // 通知消费者可以消费
}
// 消费者线程逻辑
public synchronized int consume() throws InterruptedException {
while (queue.isEmpty()) {
wait(); // 缓冲区空,等待生产者生产
}
int item = queue.poll();
System.out.println("消费: " + item + ",剩余队列大小: " + queue.size());
notifyAll(); // 通知生产者可以生产
return item;
}
}
public class Main {
public static void main(String[] args) {
SharedBuffer buffer = new SharedBuffer();
// 创建生产者线程
Thread producer = new Thread(() -> {
for (int i = 1; i <= 10; i++) {
try {
buffer.produce(i);
Thread.sleep(500); // 模拟生产耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Producer");
// 创建消费者线程
Thread consumer = new Thread(() -> {
for (int i = 1; i <= 10; i++) {
try {
buffer.consume();
Thread.sleep(1000); // 模拟消费耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Consumer");
// 启动线程
producer.start();
consumer.start();
}
}
Lock
配合使用,提供更精细的线程等待与唤醒。import java.util.concurrent.locks.*;
class AdvancedBuffer {
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private final Queue<Integer> queue = new LinkedList<>();
private final int capacity = 5;
public void produce(int item) throws InterruptedException {
lock.lock();
try {
while (queue.size() == capacity) {
notFull.await(); // 等待"非满"条件
}
queue.add(item);
System.out.println("生产: " + item + ",队列大小: " + queue.size());
notEmpty.signal(); // 触发"非空"条件
} finally {
lock.unlock();
}
}
public int consume() throws InterruptedException {
lock.lock();
try {
while (queue.isEmpty()) {
notEmpty.await(); // 等待"非空"条件
}
int item = queue.poll();
System.out.println("消费: " + item + ",剩余队列大小: " + queue.size());
notFull.signal(); // 触发"非满"条件
return item;
} finally {
lock.unlock();
}
}
}
public class Main {
public static void main(String[] args) {
AdvancedBuffer buffer = new AdvancedBuffer();
// 创建生产者线程(Lambda实现Runnable)
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
try {
buffer.produce(i);
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Producer").start();
// 创建消费者线程
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
try {
buffer.consume();
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Consumer").start();
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
// 创建固定大小的线程池(4个线程)
ExecutorService executor = Executors.newFixedThreadPool(4);
// 提交10个任务
for (int i = 1; i <= 10; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("任务 " + taskId + " 正在由 "
+ Thread.currentThread().getName() + " 执行");
try {
Thread.sleep(1000); // 模拟任务耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// 关闭线程池(不再接受新任务)
executor.shutdown();
}
}
线程安全容器:避免手动同步。
CopyOnWriteArrayList
:读多写少场景。ConcurrentHashMap
:高并发哈希表。BlockingQueue
:阻塞队列(如LinkedBlockingQueue
)。// ConcurrentHashMap 示例
import java.util.concurrent.ConcurrentHashMap;
public class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// 创建多个写线程
for (int i = 0; i < 5; i++) {
final int threadId = i;
new Thread(() -> {
for (int j = 0; j < 100; j++) {
String key = "key-" + threadId + "-" + j;
map.put(key, j);
}
System.out.println("写线程 " + threadId + " 完成");
}).start();
}
// 创建读线程
new Thread(() -> {
while (true) {
System.out.println("当前Map大小: " + map.size());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
synchronized
,适用于高并发场景。import java.util.concurrent.atomic.AtomicInteger;
public class AtomicExample {
private static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
count.incrementAndGet(); // 原子操作
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Final count: " + count.get()); // 正确输出20000
}
}
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) throws InterruptedException {
final int TASK_COUNT = 3;
CountDownLatch latch = new CountDownLatch(TASK_COUNT);
// 创建并启动多个任务线程
for (int i = 1; i <= TASK_COUNT; i++) {
final int taskId = i;
new Thread(() -> {
System.out.println("任务 " + taskId + " 开始执行");
try {
Thread.sleep(2000); // 模拟任务耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务 " + taskId + " 完成");
latch.countDown(); // 计数器减1 多个线程调用 latch.countDown()
}).start();
}
// 主线程等待所有任务完成
latch.await();
System.out.println("所有任务已完成,继续主线程逻辑");
}
}
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All threads reached barrier"));
// 每个线程调用 barrier.await()
四个必要条件:
// 死锁示例
// Thread 1: lock A → try lock B
// Thread 2: lock B → try lock A
public class DeadlockDemo {
private static final Object lockA = new Object();
private static final Object lockB = new Object();
public static void main(String[] args) {
// 线程1:先获取lockA,再请求lockB
new Thread(() -> {
synchronized (lockA) {
System.out.println("线程1 持有lockA");
try {
Thread.sleep(100); // 模拟操作耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockB) {
System.out.println("线程1 获取lockB");
}
}
}).start();
// 线程2:先获取lockB,再请求lockA
new Thread(() -> {
synchronized (lockB) {
System.out.println("线程2 持有lockB");
synchronized (lockA) {
System.out.println("线程2 获取lockA");
}
}
}).start();
}
}
解决方案:
// 避免死锁(统一锁顺序)
public class DeadlockSolution {
private static final Object lockA = new Object();
private static final Object lockB = new Object();
public static void main(String[] args) {
// 所有线程按相同顺序获取锁(先lockA后lockB)
new Thread(() -> acquireLocks(lockA, lockB, "线程1")).start();
new Thread(() -> acquireLocks(lockA, lockB, "线程2")).start();
}
private static void acquireLocks(Object firstLock, Object secondLock, String threadName) {
synchronized (firstLock) {
System.out.println(threadName + " 持有 " + firstLock);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (secondLock) {
System.out.println(threadName + " 获取 " + secondLock);
}
}
}
}
线程不断重试失败的操作(如谦让式资源释放),但无法推进。
// 活锁示例:两个线程互相让出CPU
while (true) {
if (tryLock(lockA)) {
if (tryLock(lockB)) { /* ... */ }
else { unlock(lockA); }
}
Thread.yield(); // 让出CPU但未解决问题
}
public class LivelockDemo {
static class Worker {
private boolean active = false;
public void work(Runnable task, Worker otherWorker) {
while (!active) {
if (otherWorker.active) {
System.out.println("让出执行权...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue;
}
try {
active = true;
task.run();
active = false;
} catch (Exception e) {
active = false;
}
}
}
}
public static void main(String[] args) {
final Worker worker1 = new Worker();
final Worker worker2 = new Worker();
new Thread(() -> worker1.work(() -> System.out.println("Worker1执行任务"), worker2)).start();
new Thread(() -> worker2.work(() -> System.out.println("Worker2执行任务"), worker1)).start();
}
}
资源竞争和性能问题是并发编程中的核心挑战之一。以下通过具体示例展示资源竞争导致的数据错误,以及不同锁策略对性能的影响,并给出优化方案。
ReadWriteLock
分离读锁与写锁。public class UnsafeCounterExample {
private static int count = 0;
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
count++; // 非原子操作:read → modify → write
}
};
// 启动两个线程同时修改count
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
// 预期结果:20000,实际结果可能小于20000
System.out.println("Final count: " + count);
}
}
问题分析:
count++
是非原子操作,实际包含以下步骤:int tmp = count; // Step 1: 读取当前值
tmp = tmp + 1; // Step 2: 修改值
count = tmp; // Step 3: 写回新值
count=100
→ 线程B读取count=100
→ 线程A写入101
→ 线程B写入101
101
,而非预期的102
。输出示例:
Final count: 15342 // 结果不确定,因线程竞争而异
public class CoarseLockExample {
private static final Object lock = new Object();
private static int count = 0;
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
for (int i = 0; i < 100000; i++) {
synchronized (lock) { // 粗粒度锁:锁住整个循环
count++;
}
}
};
long start = System.currentTimeMillis();
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
long end = System.currentTimeMillis();
System.out.println("Final count: " + count);
System.out.println("耗时: " + (end - start) + "ms");
}
}
问题分析:
synchronized
块内,每次循环都会获取/释放锁。输出示例:
Final count: 200000
耗时: 120ms // 实际时间因机器性能而异,但明显较长
public class FineGrainedLockExample {
private static final Object lock = new Object();
private static int count = 0;
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
int localCount = 0;
for (int i = 0; i < 100000; i++) {
localCount++; // 先在线程本地累加
}
synchronized (lock) { // 仅对最终合并操作加锁
count += localCount;
}
};
long start = System.currentTimeMillis();
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
long end = System.currentTimeMillis();
System.out.println("Final count: " + count);
System.out.println("耗时: " + (end - start) + "ms");
}
}
优化分析:
localCount
中累加,最后仅对合并操作加锁。输出示例:
Final count: 200000
耗时: 5ms // 性能显著提升
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockExample {
private static final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private static int value = 0;
public static void main(String[] args) {
// 写线程(频繁修改数据)
Runnable writer = () -> {
for (int i = 0; i < 1000; i++) {
rwLock.writeLock().lock();
try {
value++;
Thread.sleep(1); // 模拟写操作耗时
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
rwLock.writeLock().unlock();
}
}
};
// 读线程(频繁读取数据)
Runnable reader = () -> {
for (int i = 0; i < 1000; i++) {
rwLock.readLock().lock();
try {
System.out.println("读取 value: " + value);
Thread.sleep(1); // 模拟读操作耗时
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
rwLock.readLock().unlock();
}
}
};
// 启动2个写线程和4个读线程
new Thread(writer).start();
new Thread(writer).start();
new Thread(reader).start();
new Thread(reader).start();
new Thread(reader).start();
new Thread(reader).start();
}
}
优化分析:
资源竞争问题:
synchronized
、Lock
)保证原子性。性能优化策略:
ReadWriteLock
)区分读写操作,提升并发度。AtomicInteger
)或并发容器(ConcurrentHashMap
)。性能测试建议:
Executor
、ConcurrentHashMap
)。final
字段和不可变对象(如String
)。synchronized
、Lock
、原子类、并发容器。