Java并发编程基础:线程与同步
Java并发编程基础:线程与同步
概述
并发编程是Java的重要特性,它允许多个线程同时执行任务。本教程介绍线程的创建、同步机制和线程安全问题。
1. 创建线程
方式1:继承Thread类
public class ThreadDemo {
public static void main(String[] args) {
// 创建线程
Thread thread1 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("线程1: " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread1.start();
// 方式2:实现Runnable接口
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("线程2: " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread2 = new Thread(runnable);
thread2.start();
// 方式3:Lambda表达式(Java 8+)
Thread thread3 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("线程3: " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread3.start();
}
}
方式2:实现Callable接口
import java.util.concurrent.*;
public class CallableDemo {
public static void main(String[] args) {
// 创建Callable任务
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
};
// 使用FutureTask包装
FutureTask<Integer> futureTask = new FutureTask<>(callable);
// 启动线程
Thread thread = new Thread(futureTask);
thread.start();
try {
// 获取结果
Integer result = futureTask.get();
System.out.println("计算结果: " + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2. 线程同步
synchronized关键字
public class SynchronizedDemo {
private int count = 0;
// 同步方法
public synchronized void increment() {
count++;
}
// 同步代码块
public void decrement() {
synchronized (this) {
count--;
}
}
public int getCount() {
return count;
}
public static void main(String[] args) throws InterruptedException {
SynchronizedDemo demo = new SynchronizedDemo();
// 创建多个线程
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < 1000; j++) {
demo.increment();
}
});
threads[i].start();
}
// 等待所有线程完成
for (Thread thread : threads) {
thread.join();
}
System.out.println("最终计数: " + demo.getCount());
}
}
Lock接口
import java.util.concurrent.locks.*;
public class LockDemo {
private final ReentrantLock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public void decrement() {
lock.lock();
try {
count--;
} finally {
lock.unlock();
}
}
public int getCount() {
return count;
}
// 读写锁
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock = rwLock.readLock();
private final Lock writeLock = rwLock.writeLock();
private String data = "";
public String readData() {
readLock.lock();
try {
return data;
} finally {
readLock.unlock();
}
}
public void writeData(String newData) {
writeLock.lock();
try {
data = newData;
} finally {
writeLock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
LockDemo demo = new LockDemo();
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < 1000; j++) {
demo.increment();
}
});
threads[i].start();
}
for (Thread thread : threads) {
thread.join();
}
System.out.println("最终计数: " + demo.getCount());
}
}
3. 线程通信
wait/notify
public class WaitNotifyDemo {
private final Object lock = new Object();
private boolean hasData = false;
public void produce() throws InterruptedException {
synchronized (lock) {
while (hasData) {
lock.wait();
}
System.out.println("生产数据");
hasData = true;
lock.notifyAll();
}
}
public void consume() throws InterruptedException {
synchronized (lock) {
while (!hasData) {
lock.wait();
}
System.out.println("消费数据");
hasData = false;
lock.notifyAll();
}
}
public static void main(String[] args) {
WaitNotifyDemo demo = new WaitNotifyDemo();
// 生产者线程
Thread producer = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
demo.produce();
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 消费者线程
Thread consumer = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
demo.consume();
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
producer.start();
consumer.start();
}
}
4. 实际应用示例
线程池
import java.util.concurrent.*;
public class ThreadPoolDemo {
public static void main(String[] args) {
// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(3);
// 提交任务
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("任务 " + taskId + " 执行,线程: " +
Thread.currentThread().getName());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// 关闭线程池
executor.shutdown();
try {
executor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("所有任务完成");
}
}
生产者-消费者模式
import java.util.concurrent.*;
public class ProducerConsumerDemo {
public static void main(String[] args) {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
// 生产者
Thread producer = new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
String item = "Item-" + i;
queue.put(item);
System.out.println("生产: " + item);
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 消费者
Thread consumer = new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
String item = queue.take();
System.out.println("消费: " + item);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
producer.start();
consumer.start();
}
}
5. 最佳实践
- 优先使用高级并发工具:ExecutorService、BlockingQueue等
- 避免死锁:按固定顺序获取锁
- 使用volatile:确保可见性
- 最小化同步范围:只同步必要的代码
- 使用线程安全集合:ConcurrentHashMap、CopyOnWriteArrayList等
总结
并发编程是Java的重要特性。掌握线程创建、同步机制和线程安全问题,可以编写高效的并发程序。在实际编程中,优先使用高级并发工具,避免低级同步错误。