文章目录
- 1. 调用Thread类的start()方法后能否再调用start()方法?
- 2. run()和start()方法的区别?
- 3. 由问题2引出,是run()方法中的代码先执行还是当前线程中的代码先执行?
今天同学去面试时遇到了一个问题:一个线程在调用Thread类的start()方法之后,还能不能再继续调用start()方法,由此引起了我的一些思考。
1. 调用Thread类的start()方法后能否再调用start()方法?
答案肯定是不能的。
我们来看一下例子:
public class ThreadTest {public static void main(String[] args){Thread thread = new Thread();thread.start();thread.start();}}
运行结果如下:
Exception in thread "main" java.lang.IllegalThreadStateExceptionat java.base/java.lang.Thread.start(Thread.java:794)
再进入start()方法,会发现有一个对线程状态的判断,当线程的状态不为0的时候,就抛出异常。这是因为当一个线程启动时,线程便会由新生状态进入就绪状态,JVM会将线程的状态由0变为1,线程在运行时的状态为2。当再次调用start()方法时,就会发现该线程并非是新生线程,从而抛出异常。
if (threadStatus != 0)throw new IllegalThreadStateException();
另外,我们需要注意一点,start()方法是由synchronized修饰的,所以是线程安全的。
2. run()和start()方法的区别?
该问题可谓是面试中经常会问到的问题,具体测试代码如下:
public class ThreadTest {public static void main(String[] args){System.out.println("main的线程Id:" + Thread.currentThread().getId());Thread thread1 = new Thread(() -> System.out.println("thread1的线程Id:" + Thread.currentThread().getId()));Thread thread2 = new Thread(() -> System.out.println("thread2的线程Id:" + Thread.currentThread().getId()));thread1.start();thread2.run();}}
从执行结果中我们可以发现,thread1的线程Id与主线程的有所不同,而thread2的线程Id与主线程是相同的,所以我们可以判定,start()方法是新起一个线程,而run()方法只是一个普通方法,不会新起线程,而是在当前线程中执行。
main的线程Id:1
thread2的线程Id:1
thread1的线程Id:14
3. 由问题2引出,是run()方法中的代码先执行还是当前线程中的代码先执行?
具体测试代码如下:
public class ThreadTest {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> System.out.println("thread的线程Id:" + Thread.currentThread().getId()));thread.run();TimeUnit.SECONDS.sleep(10);}}
如果是run()方法中的代码先执行,那么应该是先打印线程Id,然后当前线线程休眠,如果是当前线程中的代码先执行,那么应该是当前线程休眠,而不会打印线程Id。实际我们可以将run()方法看出是一个普通的方法调用,因此当调用run()方法时,会先执行run()方法中的代码。
具体测试结果如下: