Java 多线程是指通过同时运行多个线程来提高程序的并发性和性能。在 Java 中,线程是并发执行的基本单位,每个线程都有自己独立的执行路径。了解线程的生命周期、线程操作及线程同步的机制对于高效编写并发程序至关重要。
本篇将深入讲解 Java 多线程的三个核心主题:线程状态、线程操作和线程同步,并通过代码示例进行讲解。
Java 中的线程有六种状态,每个状态表示线程在不同执行阶段的状态。线程状态的转化由 Java 虚拟机(JVM)和操作系统共同管理。
+--------------------+
| New |
+--------------------+
|
v
+--------------------+ start()
| Runnable | <-----------------+
+--------------------+ |
| |
v |
+--------------------+ run() |
| Running | -------------------+
+--------------------+
|
v
+--------------------+
| Blocked |
+--------------------+
|
v
+--------------------+ wait(), join(), sleep()
| Waiting |
+--------------------+
|
v
+--------------------+
| Timed Waiting |
+--------------------+
|
v
+--------------------+
| Terminated |
+--------------------+
线程的生命周期控制是通过线程操作来实现的。在 Java 中,我们可以使用 Thread
类或实现 Runnable
接口来创建线程。Java 提供了一些常用的线程操作,如启动线程、等待线程、暂停线程等。
通过继承 Thread
类并重写其 run()
方法来实现自定义线程行为。
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running...");
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // 启动线程
}
}
实现 Runnable
接口并将其传递给 Thread
对象来创建线程。这种方式更灵活,适合线程池使用。
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable thread is running...");
}
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start(); // 启动线程
}
}
start()
:启动线程,调用该方法会将线程从新建状态转变为就绪状态。sleep(long millis)
:使当前线程休眠指定的时间,在休眠期间不会占用 CPU 资源。join()
:等待当前线程执行完毕,通常用于一个线程等待另一个线程结束后继续执行。yield()
:让出 CPU 使用权,当前线程会进入就绪状态,可能会被其他线程抢占。interrupt()
:中断线程的执行,通常用于停止线程的工作。setPriority(int priority)
:设置线程的优先级,优先级的值范围是 1-10,默认是 5。class MyThread extends Thread {
@Override
public void run() {
try {
System.out.println("Thread is going to sleep...");
Thread.sleep(2000);
System.out.println("Thread is awake...");
} catch (InterruptedException e) {
System.out.println("Thread was interrupted!");
}
}
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start(); // 启动线程
thread.join(); // 等待线程执行完毕
System.out.println("Main thread finished");
}
}
在多线程环境下,多个线程同时操作共享资源可能会引发并发问题,如数据的不一致性、脏数据等。为了避免这些问题,Java 提供了多种线程同步机制,确保共享资源的安全访问。
synchronized
:用于修饰方法或代码块,确保同一时间只有一个线程能够访问被修饰的代码块或方法。class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
public class TestSync {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count: " + counter.getCount()); // 输出: 2000
}
}
class Counter {
private int count = 0;
public void increment() {
synchronized (this) { // 锁定当前对象
count++;
}
}
public int getCount() {
return count;
}
}
public class TestSync {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count: " + counter.getCount()); // 输出: 2000
}
}
死锁是指两个或多个线程在执行过程中因为争夺资源而造成一种相互等待的现象,从而导致程序无法继续执行。避免死锁的常见方法包括:
tryLock
:尝试获取锁,如果不能立即获得锁则返回,避免死锁。ReentrantLock
除了 synchronized
,Java 还提供了更高级的线程同步机制:ReentrantLock
。它比 synchronized
提供了更多的功能,比如尝试获取锁、超时获取锁等。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
return count;
}
}
public class TestLock {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count: " + counter.getCount()); // 输出: 2000
}
}
、就绪、运行、阻塞、等待、超时等待和终止。了解线程状态有助于理解线程的生命周期及其转化。
2. 线程操作:Java 提供了 Thread
类和 Runnable
接口来创建线程,并通过 start()
、sleep()
、join()
等方法进行线程控制。
3. 线程同步:为了避免线程安全问题,Java 提供了 synchronized
关键字和 ReentrantLock
等机制来确保多线程环境下的共享资源安全。
通过合理的线程管理与同步机制,我们可以实现高效且安全的并发程序。
因篇幅问题不能全部显示,请点此查看更多更全内容