Java多线程编程详解

多线程基础

多线程编程是Java中的一大特色,它允许程序同时执行多个线程,提高程序的执行效率和响应能力。

创建线程的方式

1. 继承Thread类

1
2
3
4
5
6
7
8
9
10
11
12
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("线程ID: " + Thread.currentThread().getId() + " 值: " + i);
}
}
}

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

2. 实现Runnable接口

1
2
3
4
5
6
7
8
9
10
11
12
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("线程ID: " + Thread.currentThread().getId() + " 值: " + i);
}
}
}

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

3. 使用Callable接口和Future

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
}

// 使用方式
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(new MyCallable());
try {
Integer result = future.get(); // 获取线程执行结果
System.out.println("计算结果: " + result);
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdown();
}

线程的生命周期

Java线程有以下几个状态:

  • NEW:新创建但未启动的线程
  • RUNNABLE:可运行状态,包括就绪和运行中
  • BLOCKED:阻塞状态,等待获取锁
  • WAITING:等待状态,无限期等待其他线程执行特定操作
  • TIMED_WAITING:超时等待状态,有限期等待
  • TERMINATED:终止状态,线程执行完毕

线程同步

synchronized关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Counter {
private int count = 0;

// 同步方法
public synchronized void increment() {
count++;
}

// 同步代码块
public void incrementBlock() {
synchronized(this) {
count++;
}
}

public int getCount() {
return count;
}
}

Lock接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Counter {
private final Lock lock = new ReentrantLock();
private int count = 0;

public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock(); // 确保锁被释放
}
}

public int getCount() {
return count;
}
}

线程通信

wait(), notify(), notifyAll()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Message {
private String content;
private boolean empty = true;

public synchronized String read() {
while(empty) {
try {
wait(); // 等待生产者写入数据
} catch (InterruptedException e) {}
}
empty = true;
notifyAll(); // 通知生产者可以写入数据
return content;
}

public synchronized void write(String message) {
while(!empty) {
try {
wait(); // 等待消费者读取数据
} catch (InterruptedException e) {}
}
empty = false;
this.content = message;
notifyAll(); // 通知消费者可以读取数据
}
}

线程池

Java提供了Executor框架来创建和管理线程池:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 固定大小的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

// 缓存线程池,根据需要创建新线程
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

// 单线程执行器
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

// 定时任务线程池
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);

// 提交任务
fixedThreadPool.execute(() -> System.out.println("任务正在执行"));

// 关闭线程池(重要)
fixedThreadPool.shutdown();

并发工具类

CountDownLatch

用于等待一组线程完成操作:

1
2
3
4
5
6
7
8
9
10
11
12
CountDownLatch latch = new CountDownLatch(3);

// 线程执行
new Thread(() -> {
try {
Thread.sleep(1000);
latch.countDown(); // 减少计数
} catch (InterruptedException e) {}
}).start();

// 等待所有线程完成
latch.await(); // 阻塞直到计数为0

CyclicBarrier

让一组线程相互等待,直到所有线程都到达某个公共屏障点:

1
2
3
4
5
6
7
8
9
10
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("所有线程已到达屏障点");
});

// 线程执行
new Thread(() -> {
try {
barrier.await(); // 等待所有线程到达
} catch (Exception e) {}
}).start();

总结

Java的多线程编程是Java高级特性中非常重要的一部分,掌握多线程编程可以显著提升程序性能。然而,多线程编程也带来了诸如线程安全、死锁等问题,需要掌握适当的同步技术和并发工具类来规避这些问题。