文章目录
Java中的线程状态和工作原理是理解并发编程的关键部分。首先,我们来看Java线程的六种状态:
- NEW(新建): 线程对象已创建,但尚未启动。
- RUNNABLE(可运行): 线程正在Java虚拟机中运行。这包括在Java虚拟机内部等待获取监视器锁(进入同步块/方法)的线程,以及等待JVM调度以获取CPU的线程。
- BLOCKED(阻塞): 线程在尝试进入一个同步块/方法时,无法获取监视器锁,则进入阻塞状态。
- WAITING(等待): 线程在等待另一个线程执行特定动作(通常是调用
notify()
或notifyAll()
方法)。 - TIMED_WAITING(限时等待): 与
WAITING
状态类似,但线程在指定的时间间隔后会自动恢复。 - TERMINATED(终止): 线程执行完毕或因异常退出。
Java创建线程的四种方式
1. 继承Thread类
解决思路:通过继承Thread
类并重写run()
方法,然后创建该类的实例并调用其start()
方法来启动线程。
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程运行中...");
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
2. 实现Runnable接口
下滑查看解决方法
解决思路:通过实现Runnable
接口并重写run()
方法,然后创建该接口的实例,并将其传递给Thread
类的构造函数,最后调用start()
方法来启动线程。
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程运行中...");
}
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}
3. 实现Callable接口(结合Future和FutureTask)
解决思路:Callable
接口与Runnable
类似,但允许在任务完成后返回一个结果,并且可以抛出检查异常。通过Future
接口可以获取该结果。通常与FutureTask
结合使用。
import java.util.concurrent.*;
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "线程执行结果";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> task = new FutureTask<>(new MyCallable());
new Thread(task).start();
System.out.println("线程结果: " + task.get());
}
}
4. 使用线程池(ExecutorService)
解决思路:线程池用于管理一组工作线程,可以复用线程,减少线程创建和销毁的开销。ExecutorService
接口提供了管理线程池的方法。
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(5); // 创建一个固定大小的线程池
Future<String> future = executor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "线程执行结果";
}
});
System.out.println("线程结果: " + future.get());
executor.shutdown(); // 关闭线程池
}
}
以上四种方式都是Java中创建线程的常用方法,它们各自有不同的应用场景和优缺点。在实际开发中,需要根据具体需求选择最合适的方式。