JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Java线程在各个状态下调用start方法会发生什么事情?

wys521 2024-11-18 18:01:49 精选教程 27 ℃ 0 评论

在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()方法。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表