Java 提供了丰富的多线程编程支持,帮助开发者编写高效的程序来充分利用 CPU 的资源。本文将详细介绍 Java 多线程编程的基本概念、线程的生命周期、线程的优先级、线程的创建方法、以及一些重要的线程控制方法。
1. 基本概念
- 进程:一个进程包含由操作系统分配的内存空间,包含一个或多个线程。
- 线程:线程是一个动态执行的过程,一个进程中可以并发多个线程。
2. 线程的生命周期
一个线程的生命周期包括以下几个阶段:
- 新建状态:通过
new
关键字创建一个线程对象后,线程处于新建状态。 - 就绪状态:调用
start()
方法后,线程进入就绪状态,等待 JVM 调度。 - 运行状态:获取 CPU 资源后,线程进入运行状态。
- 阻塞状态:由于某些原因(如调用
sleep()
方法),线程从运行状态进入阻塞状态。 - 死亡状态:线程完成任务或被终止后,进入死亡状态。
3. 线程的优先级
每个 Java 线程都有一个优先级(1 到 10)。优先级较高的线程会优先获取 CPU 资源。默认优先级是 5。
4. 创建线程的方法
Java 提供了三种创建线程的方法:
- 通过实现
Runnable
接口 - 通过继承
Thread
类 - 通过
Callable
和Future
4.1 通过实现 Runnable
接口
实现 Runnable
接口是创建线程的最简单方法。需要实现 run()
方法。
示例:
class RunnableDemo implements Runnable {private String threadName;private Thread t;RunnableDemo(String name) {threadName = name;System.out.println("Creating " + threadName);}public void run() {System.out.println("Running " + threadName);try {for(int i = 4; i > 0; i--) {System.out.println("Thread: " + threadName + ", " + i);Thread.sleep(50);}} catch (InterruptedException e) {System.out.println("Thread " + threadName + " interrupted.");}System.out.println("Thread " + threadName + " exiting.");}public void start() {System.out.println("Starting " + threadName);if (t == null) {t = new Thread(this, threadName);t.start();}}
}public class TestThread {public static void main(String args[]) {RunnableDemo R1 = new RunnableDemo("Thread-1");R1.start();RunnableDemo R2 = new RunnableDemo("Thread-2");R2.start();}
}
4.2 通过继承 Thread
类
继承 Thread
类并重写 run()
方法。
示例:
class ThreadDemo extends Thread {private String threadName;ThreadDemo(String name) {threadName = name;System.out.println("Creating " + threadName);}public void run() {System.out.println("Running " + threadName);try {for(int i = 4; i > 0; i--) {System.out.println("Thread: " + threadName + ", " + i);Thread.sleep(50);}} catch (InterruptedException e) {System.out.println("Thread " + threadName + " interrupted.");}System.out.println("Thread " + threadName + " exiting.");}public void start() {System.out.println("Starting " + threadName);if (t == null) {t = new Thread(this, threadName);t.start();}}
}public class TestThread {public static void main(String args[]) {ThreadDemo T1 = new ThreadDemo("Thread-1");T1.start();ThreadDemo T2 = new ThreadDemo("Thread-2");T2.start();}
}
4.3 通过 Callable
和 Future
使用 Callable
接口和 FutureTask
类来创建线程。Callable
接口的 call()
方法可以返回结果,并且可以抛出异常。
示例:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class CallableThreadTest implements Callable<Integer> {public static void main(String[] args) {CallableThreadTest ctt = new CallableThreadTest();FutureTask<Integer> ft = new FutureTask<>(ctt);for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName() + " 的循环变量i的值" + i);if (i == 20) {new Thread(ft, "有返回值的线程").start();}}try {System.out.println("子线程的返回值:" + ft.get());} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}}@Overridepublic Integer call() {int i = 0;for (; i < 100; i++) {System.out.println(Thread.currentThread().getName() + " " + i);}return i;}
}
5. 线程控制方法
Thread
类提供了多种控制线程的方法,如 start()
, run()
, join()
, sleep()
, interrupt()
等。
5.1 常用的 Thread
方法
start()
:启动线程并使其进入就绪状态。run()
:线程执行的主体。setName(String name)
:设置线程名称。setPriority(int priority)
:设置线程优先级。setDaemon(boolean on)
:将线程标记为守护线程或用户线程。join(long millis)
:等待该线程终止的时间最长为 millis 毫秒。interrupt()
:中断线程。isAlive()
:测试线程是否处于活动状态。
5.2 静态方法
yield()
:暂停当前正在执行的线程对象,并执行其他线程。sleep(long millis)
:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。holdsLock(Object x)
:当且仅当当前线程在指定的对象上保持监视器锁时,才返回true
。currentThread()
:返回对当前正在执行的线程对象的引用。dumpStack()
:将当前线程的堆栈跟踪打印至标准错误流。
示例:
public class ThreadClassDemo {public static void main(String[] args) {Runnable hello = new DisplayMessage("Hello");Thread thread1 = new Thread(hello);thread1.setDaemon(true);thread1.setName("hello");System.out.println("Starting hello thread...");thread1.start();Runnable bye = new DisplayMessage("Goodbye");Thread thread2 = new Thread(bye);thread2.setPriority(Thread.MIN_PRIORITY);thread2.setDaemon(true);System.out.println("Starting goodbye thread...");thread2.start();System.out.println("Starting thread3...");Thread thread3 = new GuessANumber(27);thread3.start();try {thread3.join();} catch (InterruptedException e) {System.out.println("Thread interrupted.");}System.out.println("Starting thread4...");Thread thread4 = new GuessANumber(75);thread4.start();System.out.println("main() is ending...");}
}
线程的高级概念
1. 线程同步
在多线程环境中,多个线程可能会同时访问共享资源,导致数据不一致的问题。Java 提供了同步机制,使用 synchronized
关键字可以解决这个问题。
2. 线程间通信
Java 提供了多种线程间通信的方法,如 wait()
, notify()
, notifyAll()
。
3. 线程死锁
当两个或多个线程互相等待对方释放资源时,程序会陷入死锁状态。这是多线程编程中需要避免的情况。
4. 线程控制:挂起、停止和恢复
虽然 Thread
类提供了 suspend()
, resume()
, stop()
方法,但是它们已经被废弃,因为使用这些方法容易导致死锁等问题。推荐使用更安全的线程控制方法。
总结
通过以上内容,我们了解了 Java 多线程编程的基本概念、线程的生命周期、线程的优先级、创建线程的方法、以及一些重要的线程控制方法。掌握这些知识后,可以编写出高效的多线程程序,充分利用系统资源。