昨天栈长介绍了《Java多线程能够分组,还能这样玩!》线程分组的妙用。今天,栈长会详细介绍 Java 中的多线程 start() 和 run() 两个方法,Java 老司机请跳过,新手或者对这两个不是很理解的能够继续往下看。java
首先要知道实现多线程最基本的两种方式:面试
一、继承 java.lang.Thread
类;多线程
二、实现 java.lang.Runnable
接口;异步
其中 Thread 类也是实现了 Runnable 接口,而 Runnable 接口定义了惟一的一个 run() 方法,因此基于 Thread 和 Runnable 建立多线程都须要实现 run() 方法,是多线程真正运行的主方法。this
@FunctionalInterface public interface Runnable { public abstract void run(); }
而 start() 方法则是 Thread 类的方法,用来异步启动一个线程,而后主线程马上返回。该启动的线程不会立刻运行,会放到等待队列中等待 CPU 调度,只有线程真正被 CPU 调度时才会调用 run() 方法执行。线程
因此 start() 方法只是标识线程为就绪状态的一个附加方法,如下 start() 方法的源码,其中 start0() 是一个本地 native 方法。code
public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } }
请注意,start() 方法被标识为 synchronized 的,即为了防止被屡次启动的一个同步操做。继承
那么你会问了,为何要有两个方法,直接用一个 run() 方法不就好了吗!? 还真不行,若是直接调用 run() 方法,那就等于调用了一个普通的同步方法,达不到多线程运行的异步执行,来看下面的例子。接口
/** * 公众号:Java技术栈 */ public static void main(String[] args) { Thread thread = new Thread(() -> { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Java技术栈"); }); long start = System.currentTimeMillis(); thread.start(); System.out.println(System.currentTimeMillis() - start); start = System.currentTimeMillis(); thread.run(); System.out.println(System.currentTimeMillis() - start); }
程序输出:队列
0 Java技术栈 3000 Java技术栈
从程序输出结果能够看出,启动 start 方法先后只用了 0 毫秒,而启动 run 方法则阻塞了 3000 毫秒等程序执行完再继续执行,这就是同步与异步的一个最重要的区别。
看完这篇,你应该对 start 和 run 方法有了一个大概的掌握吧,不再怕面试官问你这两个的区别了吧!
动手转发给更多的朋友吧!
更多 Java 多线程技术文章请在Java技术栈公众号后台回复关键字:多线程。
本文原创首发于公众号:Java技术栈(id:javastack),关注公众号在后台回复 "多线程" 可获取更多,转载请原样保留本信息。