网站首页 > 精选教程 正文
在Java中,如果一个线程对象的start()方法被调用了两次或多次,通常情况下会导致IllegalThreadStateException异常的抛出。
当线程对象的start()方法被调用时,会启动一个新的线程,并执行该线程对象的run()方法。但是,一旦线程启动后,就不能再次启动该线程。如果尝试调用已经启动的线程对象的 start()方法,Java就会抛出IllegalThreadStateException异常。
这个设计是为了防止线程在运行时出现不可预测的行为,因为一个线程对象在运行后就被认为是“活跃”的,再次启动它可能会导致竞争条件和其他问题。因此,为了确保线程的正确性,Java引入了这种机制来防止对已经启动的线程再次启动。
下面我们就来Java中线程在各个状态下调用start方法会发生什么?
正在RUNNING中的线程再次调用start会发生什么?
在Java中,线程的状态是通过一个枚举类Thread.State来表示的。Thread类中维护了一个private int类型的threadStatus字段,用于记录线程的状态。threadStatus的值对应着 Thread.State枚举中的不同状态。如下所示。
public class Thread implements Runnable {
// 线程状态
private volatile int threadStatus;
// 线程状态枚举类
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
// 线程启动方法
public synchronized void start() {
// ...
if (threadStatus != 0)
throw new IllegalThreadStateException();
// ...
threadStatus = RUNNABLE;
// ...
}
// 线程运行方法
@Override
public void run() {
// ...
if (threadStatus != NEW)
throw new IllegalThreadStateException();
// ...
threadStatus = RUNNABLE;
// ...
}
}
在Thread类中,start()方法用于启动线程,而run()方法用于线程的实际执行。在 start()方法中,会检查线程状态是否为0(表示新建状态),如果不是则抛出IllegalThreadStateException异常。在run()方法中也会进行类似的检查。
当一个线程已经处于RUNNABLE状态(也就是运行中)时,如果再次调用start()方法,由于状态已经不是 0(新建状态),因此会抛出IllegalThreadStateException异常。这是因为线程对象已经被启动并处于执行状态,再次启动同一个线程会导致线程状态的不一致性,可能会引发各种并发问题。
在TERMINATED中的线程调用start方法?
在Java中,当线程处于TERMINATED状态时,再次调用start()方法不会抛出异常,但是也不会启动新的线程。因为线程处于终止状态,它已经完成了其任务,不再处于可运行状态。
在Thread类的start()方法中,会对线程状态进行检查,但通常情况下只会抛出异常,如果线程已经处于TERMINATED状态,则不会执行异常抛出代码段。因此,调用处于终止状态的线程对象的start()方法并不会导致异常,但也不会有任何效果。
下面是一个简化的示例
public class Main {
public static void main(String[] args) {
Thread terminatedThread = new Thread(() -> {
System.out.println("Thread is running...");
});
terminatedThread.start(); // 启动线程
try {
terminatedThread.join(); // 等待线程执行完成
} catch (InterruptedException e) {
e.printStackTrace();
}
// 线程已经执行完成,处于 TERMINATED 状态
System.out.println("Thread state: " + terminatedThread.getState()); // 输出 TERMINATED
terminatedThread.start(); // 再次调用 start() 方法
System.out.println("After calling start() again...");
System.out.println("Thread state: " + terminatedThread.getState()); // 输出 TERMINATED
}
}
在这个示例中,当已经处于终止状态的线程对象再次调用start()方法时,不会产生异常,但也不会启动新的线程。线程状态依然保持在TERMINATED。
Blocked状态的线程调用start方法?
当线程处于BLOCKED状态时调用start()方法,情况与处于TERMINATED状态时相似。在BLOCKED状态下调用start()方法不会抛出异常,但也不会启动新的线程,因为线程在BLOCKED状态下被阻塞,无法执行任务。
BLOCKED状态表示线程因为竞争锁而被阻塞,等待获取对象的监视器锁。当线程被阻塞时,它暂时失去了运行的机会,直到获取到锁并且进入到RUNNABLE状态,才有可能继续执行。下面是一个简化的示例。说明了处于BLOCKED状态的线程调用start()方法的情况
public class Main {
private static final Object lock = new Object();
public static void main(String[] args) {
Thread blockedThread = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread is running...");
}
});
blockedThread.start(); // 启动线程并获取 lock 锁
try {
Thread.sleep(100); // 为了确保线程获取锁并处于 BLOCKED 状态
} catch (InterruptedException e) {
e.printStackTrace();
}
// 创建另一个线程,尝试获取 lock 锁
Thread competingThread = new Thread(() -> {
synchronized (lock) {
System.out.println("Competing thread acquired lock.");
}
});
competingThread.start(); // 启动竞争线程,此时 blockedThread 处于 BLOCKED 状态
System.out.println("Blocked thread state: " + blockedThread.getState()); // 输出 BLOCKED
blockedThread.start(); // 再次调用 start() 方法
System.out.println("After calling start() again...");
System.out.println("Blocked thread state: " + blockedThread.getState()); // 输出 BLOCKED
}
}
在这个示例中,blockedThread被阻塞,处于BLOCKED状态,此时再次调用其start() 方法不会抛出异常,但也不会启动新的线程。线程状态依然保持在BLOCKED。
Waiting状态线程调用start方法?
当线程处于WAITING状态时调用start()方法,同样不会抛出异常,但也不会启动新的线程。
WAITING状态表示线程正在等待其他线程执行特定操作。例如,线程调用了Object.wait()方法或Thread.join()方法时,会使线程进入WAITING状态,直到被唤醒或者被等待的线程执行完成。
在WAITING状态下调用start()方法并不会有任何效果,因为线程已经处于等待状态,无法直接转变为可运行状态。调用start()方法仅在线程处于新建状态(NEW)时才会创建并启动新线程。如下所示。
public class Main {
public static void main(String[] args) {
Object lock = new Object();
Thread waitingThread = new Thread(() -> {
synchronized (lock) {
try {
lock.wait(); // 线程进入 WAITING 状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
waitingThread.start(); // 启动线程并使其等待
System.out.println("Waiting thread state: " + waitingThread.getState()); // 输出 WAITING
waitingThread.start(); // 再次调用 start() 方法
System.out.println("After calling start() again...");
System.out.println("Waiting thread state: " + waitingThread.getState()); // 输出 WAITING
}
}
在这个示例中,waitingThread调用了Object.wait()方法进入WAITING状态,此时再次调用start()方法不会抛出异常,但也不会启动新的线程。线程状态依然保持在WAITING。
TimedWaiting状态线程调用Start方法?
当线程处于TIMED_WAITING状态时调用start()方法,同样不会抛出异常,但也不会启动新的线程。
TIMED_WAITING状态表示线程正在等待一段时间。例如,线程调用了Thread.sleep(long millis)方法或Object.wait(long timeout)方法时,会使线程进入TIMED_WAITING状态。
在TIMED_WAITING状态下调用start()方法并不会有任何效果,因为线程已经处于等待状态,无法直接转变为可运行状态。调用start()方法仅在线程处于新建状态(NEW)时才会创建并启动新线程。如下所示。
public class Main {
public static void main(String[] args) {
Thread timedWaitingThread = new Thread(() -> {
try {
Thread.sleep(1000); // 线程进入 TIMED_WAITING 状态
} catch (InterruptedException e) {
e.printStackTrace();
}
});
timedWaitingThread.start(); // 启动线程并使其等待一段时间
System.out.println("Timed waiting thread state: " + timedWaitingThread.getState()); // 输出 TIMED_WAITING
timedWaitingThread.start(); // 再次调用 start() 方法
System.out.println("After calling start() again...");
System.out.println("Timed waiting thread state: " + timedWaitingThread.getState()); // 输出 TIMED_WAITING
}
}
在这个示例中,timedWaitingThread调用了Thread.sleep(1000)方法进入TIMED_WAITING状态,此时再次调用start()方法不会抛出异常,但也不会启动新的线程。线程状态依然保持在TIMED_WAITING。
总结
以上就是Java线程在不同状态下调用start方法会发生的情况,当然如果线程是在New状态下,那么此时它调用start方法属于正常的行为,NEW状态表示线程对象已经被创建但尚未启动。调用start()方法会使线程进入RUNNABLE 状态,并开始执行其run()方法。
- 上一篇: 为什么Java中线程没有Running状态
- 下一篇: 浅谈Java线程:线程基础知识扫盲
猜你喜欢
- 2024-11-18 Java并发编程线程状态转换
- 2024-11-18 Java面试必考问题:线程的生命周期
- 2024-11-18 Java 19 虚拟线程的状态变化,停驻与锁定
- 2024-11-18 Java线程生命周期详解?
- 2024-11-18 线程从创建最终消亡,要经历的若干状态,你了解其中的多少?
- 2024-11-18 java线程状态之WAITING(等待)
- 2024-11-18 浅谈Java线程:线程基础知识扫盲
- 2024-11-18 为什么Java中线程没有Running状态
- 2024-11-18 阻塞模型将会使线程休眠,为什么 Java 线程状态却是 RUNNABLE?
- 2024-11-18 可动态调节参数的线程池实现
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)