Java 学习系列(13):Java 多线程详解
1. 多线程概述
在 Java 中,多线程是指同时运行多个线程的能力。线程是程序执行的基本单元,每个线程都有自己的执行路径。通过多线程,可以提高程序的并发性和执行效率,尤其是在多核 CPU 上。
Java 提供了强大的多线程支持,通过 Thread 类或实现 Runnable 接口来创建和管理线程。
2. 创建线程的方式
Java 中有两种主要的方式来创建线程:
2.1 继承 Thread 类
通过继承 Thread 类,并重写其 run() 方法来定义线程要执行的任务。
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程正在执行...");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // 启动线程
}
}
2.2 实现 Runnable 接口
另一种方式是实现 Runnable 接口,并将其作为参数传递给 Thread 类的构造函数。这样可以避免继承限制,使类可以同时继承其他类。
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程正在执行...");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start(); // 启动线程
}
}
3. 线程的生命周期
Java 中线程的生命周期包括以下几个状态:
- 新建状态(New):线程被创建,但尚未启动。
- 就绪状态(Runnable):线程准备好执行,等待 CPU 分配时间片。
- 运行状态(Running):线程正在执行。
- 阻塞状态(Blocked):线程被阻塞,等待资源或条件。
- 终止状态(Terminated):线程执行完成或被强制终止。
4. 线程同步
在多线程编程中,多个线程可能会共享同一资源,导致数据不一致。为了避免这种情况,需要使用线程同步。
4.1 synchronized 关键字
synchronized 用于修饰方法或代码块,确保同一时刻只有一个线程可以访问同步的代码块或方法。
4.1.1 同步方法
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized void decrement() {
count--;
}
public int getCount() {
return count;
}
}
public class SynchronizedExample {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.decrement();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("最终计数: " + counter.getCount());
}
}
4.2 同步代码块
同步代码块用于在方法内对共享资源进行同步,而不是整个方法。
class Counter {
private int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public void decrement() {
synchronized (this) {
count--;
}
}
public int getCount() {
return count;
}
}
public class SynchronizedExample {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.decrement();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("最终计数: " + counter.getCount());
}
}
5. 线程间通信
在多线程环境中,线程之间可以通过 线程间通信 来协作,常用的方法有 wait()、notify() 和 notifyAll()。
5.1 wait() 和 notify()
wait():使当前线程进入等待状态,并释放锁。notify():唤醒一个等待的线程。notifyAll():唤醒所有等待的线程。
class Producer implements Runnable {
private final Object lock;
public Producer(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
System.out.println("生产者生产产品...");
lock.notify(); // 唤醒消费者线程
}
}
}
class Consumer implements Runnable {
private final Object lock;
public Consumer(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
try {
lock.wait(); // 等待生产者生产产品
System.out.println("消费者消费产品...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadCommunicationExample {
public static void main(String[] args) {
Object lock = new Object();
Thread producer = new Thread(new Producer(lock));
Thread consumer = new Thread(new Consumer(lock));
consumer.start();
producer.start();
}
}
6. 线程池
在多线程编程中,线程池是一种非常重要的技术,它可以避免频繁创建和销毁线程的开销,提高系统的性能和资源利用率。
6.1 使用 ExecutorService 创建线程池
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> System.out.println("任务 1 执行"));
executor.submit(() -> System.out.println("任务 2 执行"));
executor.shutdown(); // 关闭线程池
}
}
7. 总结
- 线程的创建:可以通过继承
Thread类或实现Runnable接口来创建线程。 - 线程同步:使用
synchronized来保证线程的安全访问,避免竞态条件。 - 线程间通信:通过
wait()、notify()和notifyAll()方法实现线程之间的协作。 - 线程池:线程池是管理多线程的有效方式,使用
ExecutorService来管理线程池。
下一期:《Java 学习系列(14):Java 集合框架详解》

被折叠的 条评论
为什么被折叠?



