开启一个线程,正确做法是调用线程start方法,但遇见过有调用run方法开启线程的,调用run方法肯定是错误的,虽然也执行了该执行的操作。
以上图中cpu为例。
public class ThreadTest1 { public static void main(String[] args) { // 输出当前线程名称 System.out.println(Thread.currentThread().getName()); // 创建新线程 ThreadPattern threadPattern = new ThreadPattern(); // 开启新线程 threadPattern.start(); } /** * Thread扩展类 */ private static class ThreadPattern extends Thread{ @Override public void run() { super.run(); // 输出当前线程名称 System.out.println(Thread.currentThread().getName()); System.out.println("我是新新线程"); } } }
运行结果:
main Thread-0 我是新新线程
首先在main()输出当前线程为main,也就是主线程;然后创建了新线程Thread-0,并输出当前线程名称和需要输出的语句"我是新新线程"。结果也证明确实创建了新线程,也做了该做的事。
// 创建线程实例 ThreadPattern threadPattern = new ThreadPattern();
该代码只是创建了线程对象,什么也没有做,还没有真正成为线程。当调用start()时才开始成为真正的线程。 当调用start()时,start()再调用start0(),此时才算是成为真正的线程,做线程该做的事情。start0()是native方法,也就是执行start0(),才能真正调用电脑中分配的资源,利用cpu和内存做事,之前的所有准备都是逻辑处理,未真正涉及进程分配的资源。 通过观察还发现:
/* * Java thread status for tools, default indicates thread not yet started */ private volatile int threadStatus; /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0) throw new IllegalThreadStateException(); ...
threadStatus是表示线程的开启状态,等于0时表示线程未开启,不等于0时表示线程已开启,当线程开启时,再调用start()会抛出IllegalThreadStateException异常。 验证:
// 开启新线程 threadPattern.start(); threadPattern.start();
结果:
main Thread-0 我是新新线程 Exception in thread "main" java.lang.IllegalThreadStateException at java.base/java.lang.Thread.start(Thread.java:791) at thread.ThreadTest1.main(ThreadTest1.java:17)
不出意外,第二次调用start()直接抛出了IllegalThreadStateException。所以线程start()只能调用一次。
public class ThreadTest1 { public static void main(String[] args) { // 输出当前线程名称 System.out.println(Thread.currentThread().getName()); // 创建新线程 ThreadPattern threadPattern = new ThreadPattern(); // threadPattern.run(); } /** * Thread扩展类 */ private static class ThreadPattern extends Thread{ @Override public void run() { super.run(); System.out.println(Thread.currentThread().getName()); System.out.println("我是新新线程"); } } }
结果:
main main 我是新新线程
结果发现虽然执行了需要执行的操作,但是并没有创建新的线程,还是在主线程main中执行的相关操作。此时创建的threadPattern只是一个简单的对象,和线程没有关系,而threadPattern.run()仅仅是调用了该对象中一个普通不能再普通的方法,仅此而已,和线程无关。