一、线程的使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void main (String[] args) { Thread thread1 = new Thread(new Runnable() { @Override public void run () { System.out.println("执行线程1" ); } }); thread1.start(); Thread thread2 = new Thread(new Runnable() { @Override public void run () { System.out.println("执行线程2" ); } }); thread2.run(); }
创建以上两个线程,执行结果:
线程1与线程2都执行了 run(),但线程1是通过 start() 执行的,线程2是直接调用 run() 执行的。
二、start() 与 run() 的区别 为了更精准地找到两种调用之间的区别,需要打印线程相关的信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void main (String[] args) { Thread thread1 = new Thread(new Runnable() { @Override public void run () { Thread currentThread = Thread.currentThread(); System.out.println("执行线程1; 线程名称:" + currentThread.getName()); } }); thread1.start(); Thread thread2 = new Thread(new Runnable() { @Override public void run () { Thread currentThread = Thread.currentThread(); System.out.println("执行线程2; 线程名称:" + currentThread.getName()); } }); thread2.run(); }
执行结果:
1 2 执行线程1 ; 线程名称:Thread-0 执行线程2 ; 线程名称:main
从执行结果来看,start() 调用,是通过开启一个新线程来执行 run() 的;而直接调用 run(),是主线程直接执行方法内容的。
此外,我们还可以做另一种尝试:多次执行 run() 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public static void main (String[] args) { Thread thread1 = new Thread(new Runnable() { @Override public void run () { Thread currentThread = Thread.currentThread(); System.out.println("执行线程1; 线程名称:" + currentThread.getName()); } }); thread1.run(); thread1.run(); Thread thread2 = new Thread(new Runnable() { @Override public void run () { Thread currentThread = Thread.currentThread(); System.out.println("执行线程2; 线程名称:" + currentThread.getName()); } }); thread2.start(); thread2.start(); }
执行结果:
1 2 3 4 5 6 执行线程1 ; 线程名称:main 执行线程1 ; 线程名称:main 执行线程2 ; 线程名称:Thread-1 Exception in thread "main" java.lang.IllegalThreadStateException at java.lang.Thread.start(Thread.java:708 ) at com.example.springbatchdemo.job.Test.main(Test.java:29 )
从执行结果可知,可以多次调用 run(),而 start() 只能被执行一次,这是为什么呢?我们看下 start 方法说明:
1 2 3 4 5 6 7 8 9 10 public synchronized void start () { if (threadStatus != 0 ) throw new IllegalThreadStateException();
调用 start(),首先需要判断当前线程的状态是否为 0 (NEW),如果不是,则抛异常。当第一次调用 start() 时,线程状态从 NEW (新建)变为 RUNNABLE(就绪),当第二次调用 start() 时,线程状态肯定不是 NEW。
三、总结 Thread 的 start() 与 run() 都可以完成任务执行,主要区别在:
作用机制不同:直接调用 run(),相当于在当前线程中执行普通方法;调用 start(),是开启一个新的线程来执行 run();
执行速度不同:调用 run() 会立即执行任务,调用 start() 是将线程的状态改为就绪状态,等待空闲 CPU,不会立即执行;
调用次数不同:run() 可以被重复调用,而 start() 只能被调用一次。