Java 多线程系列详解:从基础到高级
多线程编程是 Java 开发中的重要主题,能够提高程序执行效率和资源利用率。本文是 Java 多线程系列的第一篇,将从多线程的基础知识入手,详细讲解多线程的创建方式、生命周期、常用方法、线程同步机制以及常见问题。
一、什么是多线程?
多线程是一种并发执行任务的方式,允许程序在多个线程之间切换,从而同时运行多个任务,提高程序的执行效率和响应速度。
二、Java 多线程的实现方式
Java 提供了多种创建线程的方法。
1. 继承 Thread 类
通过继承 Thread 类,重写 run() 方法来定义线程执行的内容。
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程执行:" + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start(); // 启动线程
}
}
2. 实现 Runnable 接口(推荐)
这种方式更灵活,推荐使用。
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("执行线程:" + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable());
t1.start(); // 启动线程
}
}
3. 实现 Callable 接口(带返回值)
Callable 接口支持返回值和异常处理,比 Runnable 更强大。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "线程执行:" + Thread.currentThread().getName();
}
}
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
Thread t1 = new Thread(futureTask);
t1.start();
System.out.println(futureTask.get());
}
}
三、线程的生命周期
Java 中线程的生命周期主要包括以下几个阶段:
- 新建(New) :线程对象被创建,但未启动。
- 就绪(Runnable) :调用
start()方法,等待 CPU 调度。 - 运行(Running) :CPU 调度后开始执行
run()方法。 - 阻塞(Blocked/Waiting) :线程在等待资源时进入该状态。
- 终止(Terminated) :线程执行完成或被中断。
四、线程常用方法及示例
| 方法 | 描述 | 示例代码 |
|---|---|---|
start() | 启动线程 | t1.start(); |
run() | 定义线程运行的逻辑 | t1.run(); (不推荐) |
sleep(long) | 让线程休眠一段时间 | Thread.sleep(1000); |
yield() | 暂时放弃 CPU 使用权 | Thread.yield(); |
join() | 等待线程执行完成 | t1.join(); |
interrupt() | 中断线程 | t1.interrupt(); |
isAlive() | 检查线程是否存活 | t1.isAlive(); |
示例代码:
class MyThread extends Thread {
@Override
public void run() {
try {
System.out.println("线程开始:" + Thread.currentThread().getName());
Thread.sleep(1000); // 休眠 1 秒
System.out.println("线程结束:" + Thread.currentThread().getName());
} catch (InterruptedException e) {
System.out.println("线程被中断:" + Thread.currentThread().getName());
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread();
t1.start(); // 启动线程
t1.join(); // 等待线程完成
System.out.println("主线程执行完成");
}
}
五、线程安全与同步机制
1. 同步代码块(synchronized)
public class SyncExample {
public void method() {
synchronized (this) {
System.out.println("线程:" + Thread.currentThread().getName());
}
}
}
2. 同步方法
public class SyncExample {
public synchronized void syncMethod() {
System.out.println("同步方法执行:" + Thread.currentThread().getName());
}
}
3. 静态同步方法
public class SyncExample {
public static synchronized void staticMethod() {
System.out.println("静态同步方法:" + Thread.currentThread().getName());
}
}
六、常见问题与注意事项
1. 为什么使用多线程?
- 提高程序执行效率
- 提供更好的用户体验(如响应用户界面)
- 并发处理多个任务
2. 多线程的主要问题
- 数据共享问题: 多线程共享变量可能导致数据不一致。
- 死锁: 多个线程相互等待对方释放资源。
- 线程阻塞: 等待资源时导致程序挂起。
七、面试常见问题与知识点
-
Java 中如何创建线程?哪种方式更推荐? 推荐使用
Runnable接口,灵活性更高。 -
线程的生命周期是什么? 新建、就绪、运行、阻塞、终止。
-
线程间如何实现通信?
- 使用
wait()、notify()和notifyAll() - 使用
Condition和Lock
- 使用
-
线程安全的集合类有哪些?
ConcurrentHashMapCopyOnWriteArrayListBlockingQueue
通过这些基础知识,你应该对 Java 多线程的核心概念有了深入的了解。如果对某个方面感兴趣,欢迎讨论! 😊