创建线程的方式
Java 提供了两种主要方法来创建线程:
public class MyThread extends Thread { @Override public void run() { System.out.println("继承 Thread 创建线程"); } public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); // 启动线程 } }
方法 2:实现
Runnable
接口实现
Runnable
接口可以更灵活,因为 Java 不支持多继承,所以这种方式通常优于直接继承Thread
。public class MyRunnable implements Runnable { @Override public void run() { System.out.println("实现 Runnable 接口创建线程"); } public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); // 启动线程 } }
2.
Thread
类的常用方法
start()
- 用于启动线程。调用后,线程进入 就绪状态,等待 CPU 调度。
thread.start();
run()
- 定义线程的执行逻辑,但不直接调用它(直接调用不会创建新线程,必须通过
start()
运行)。- 让当前线程进入 休眠状态,暂停指定的毫秒数,然后再恢复到 就绪状态。
sleep(long millis)
try { Thread.sleep(1000); // 暂停1秒 } catch (InterruptedException e) { e.printStackTrace(); }
join()
- 等待该线程执行完毕。可以用在主线程中等待子线程完成,以确保执行顺序。
Thread thread = new Thread(new MyRunnable()); thread.start(); thread.join(); // 主线程等待子线程执行完
interrupt()
和isInterrupted()
interrupt()
方法用于打断一个线程的休眠或等待状态,发出一个中断信号。isInterrupted()
用于检查线程是否已被中断。thread.interrupt(); // 中断线程 if (thread.isInterrupted()) { System.out.println("线程已中断"); }
getId()
、getName()
和setName()
- 用于获取或设置线程的 ID 和名称。
getPriority() 和 setPriority(int priority) Thread 类有 3 种优先级常量: MIN_PRIORITY (1) NORM_PRIORITY (5) MAX_PRIORITY (10) thread.setPriority(Thread.MAX_PRIORITY); // 设置优先级为最大 System.out.println("线程优先级: " + thread.getPriority());
3.
Thread
的生命周期和状态线程在执行过程中会经历多个状态,这些状态反映了线程的执行过程和进展情况:
- NEW:线程创建后,但尚未调用
start()
。- RUNNABLE:线程已经启动,等待 CPU 调度执行。
- BLOCKED:线程等待锁定资源而处于阻塞状态。
- WAITING:线程处于等待状态,等待其他线程的通知。
- TIMED_WAITING:线程在等待指定时间后被唤醒。
- TERMINATED:线程完成执行或异常终止
4. yield() yield() 方法可以让当前执行的线程放弃 CPU 资源,将其让给其他优先级相同或更高的线程。
5. 守护线程(Daemon Thread)
守护线程在后台运行,比如垃圾回收线程。设置一个线程为守护线程后,当所有非守护线程结束时,守护线程也会自动终止。
thread.setDaemon(true); // 设置为守护线程
6. 线程同步与锁机制
在多线程环境下,资源共享容易引发线程冲突。Java 提供了
synchronized
关键字来保证线程同步,避免数据不一致的问题。
public class Counter { private int count = 0; public synchronized void increment() { count++; } public static void main(String[] args) { Counter counter = new Counter(); Thread t1 = new Thread(counter::increment); Thread t2 = new Thread(counter::increment); t1.start(); t2.start(); } }
7.
ThreadLocal
ThreadLocal
提供了线程内部的局部变量,每个线程有自己的独立副本。public class ThreadLocalExample { private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 1); public static void main(String[] args) { Thread t1 = new Thread(() -> { threadLocal.set(2); System.out.println("线程1的变量值: " + threadLocal.get()); }); Thread t2 = new Thread(() -> { System.out.println("线程2的变量值: " + threadLocal.get()); }); t1.start(); t2.start(); } }
8. 使用线程池管理
Thread
在直接使用
Thread
时,由于缺少资源管理和线程重用,较难管理大量线程。通常通过ExecutorService
线程池更好地管理Thread
对象。import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(3); for (int i = 0; i < 5; i++) { executor.submit(() -> System.out.println(Thread.currentThread().getName() + " 执行任务")); } executor.shutdown(); } }
在 Java 中,
Callable
通常和ExecutorService
配合使用,通过submit()
方法来执行,并返回一个Future
对象,该对象用于获取线程执行的结果。import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class CallableExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); Callable<String> task = () -> { Thread.sleep(1000); return "任务完成"; }; Future<String> result = executor.submit(task); try { System.out.println("等待任务完成..."); String output = result.get(); // 阻塞等待,直到结果返回 System.out.println("任务结果: " + output); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } executor.shutdown(); } }
- Future:可以通过
Future
来获取Callable
的执行结果,result.get()
会阻塞主线程,直到Callable
返回结果。- 异常处理:
Callable
支持抛出异常,能帮助捕获和处理任务中的错误。相比之下,
Callable
适合需要返回值或进行错误处理的多线程任务,而Runnable
适用于不需要返