不知道哪位古人說:人生三大境界。第一境界是:看山是山看水是水;第二境界是看山不是山看水不是水;第三境界:看山仍是山看水仍是水。
其實我想對於任何一門技術的學習都是這樣。
形而上下者爲之器,形而上者爲之道。一直很喜歡本身大一的高數老師,老師是老教授了,他講數學,會引伸到建築學,計算機科學,以及哲學再到生活中的常識。也能從其餘學科、平常生活中,提取出數學的概念。我想,這就是形而上者了。
不勝望之
很少言,這裏咱們來深刻java底層,看下java表皮之下的筋肉以及內臟。java
package thread; /** * @author xuyuanpeng * @version 1.0 * @date 2019-05-17 17:04 */ public class ThreadMain { public static void main(String[] args) { Thread thread=new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread t2=new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); log("線程1開始"); thread.start(); log("線程1結束"); log("線程2開始"); t2.run(); log("線程2結束"); } public static void log(String msg){ System.err.print(System.currentTimeMillis()); System.out.println(">>>"+msg); } public static void log(){ log(""); } }
這裏能夠思考下輸出的結果:
1
2
3
鐺鐺鐺檔異步
Connected to the target VM, address: '127.0.0.1:51304', transport: 'socket'
1558085396255>>>線程1開始
1558085396255>>>線程1結束
1558085396255>>>線程2開始
1558085397255>>>線程2結束
Disconnected from the target VM, address: '127.0.0.1:51304', transport: 'socket'socket
細心的同窗確定已經發現了
線程1是start的方式啓動,而線程2是run方法啓動
差別在哪?
線程1執行start,並無阻塞線程
而線程2的run方法,阻塞了線程。何改咯?┓( ´∀` )┏
爲何是這樣的呢?start與run的區別究竟在哪呢?讓咱們深刻她,張愛玲說,瞭解一個女人最好的通道就是XX,因此讓咱們深刻她,再瞭解她。ide
public synchronized void start() { /** /** * Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread. * * 一、start方法將致使當前線程開始執行。由JVM調用當前線程的run方法。 * * The result is that two threads are running concurrently: the * current thread (which returns from the call to the * <code>start</code> method) and the other thread (which executes its * <code>run</code> method). * * 二、結果是 調用start方法的當前線程 和 執行run方法的另外一個線程 同時運行。 * * It is never legal to start a thread more than once. * In particular, a thread may not be restarted once it has completed * execution. * * 三、屢次啓動線程永遠不合法。 特別是,線程一旦完成執行就不會從新啓動。 * * @exception IllegalThreadStateException if the thread was already started. * 若是線程已啓動,則拋出異常。 * @see #run() * @see #stop() */ 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. * * 四、對於由VM建立/設置的main方法線程或「system」組線程,不會調用此方法。 * 將來添加到此方法的任何新功能可能也必須添加到VM中。 * * A zero status value corresponds to state "NEW". * 五、status=0 表明是 status 是 "NEW"。 */ if (threadStatus != 0) throw new IllegalThreadStateException(); /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. * * 六、通知組該線程即將啓動,以便將其添加到線程組的列表中, * 而且減小線程組的未啓動線程數遞減。 * * */ group.add(this); boolean started = false; try { //七、調用native方法,底層開啓異步線程,並調用run方法。 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 * 八、忽略異常。 若是start0拋出一個Throwable,它將被傳遞給調用堆棧。 */ } } }
start方法用synchronized修飾,爲同步方法;
雖然爲同步方法,但不能避免屢次調用問題,用threadStatus來記錄線程狀態,若是線程被屢次start會拋出異常;threadStatus的狀態由JVM控制。
使用Runnable時,主線程沒法捕獲子線程中的異常狀態。線程的異常,應在線程內部解決。源碼分析
private native void start0();
native 是聲明本地方法,在此處是JVM中的方法。學習
/** * If this thread was constructed using a separate * <code>Runnable</code> run object, then that * <code>Runnable</code> object's <code>run</code> method is called; * otherwise, this method does nothing and returns. * <p> * Subclasses of <code>Thread</code> should override this method. * * @see #start() * @see #stop() * @see #Thread(ThreadGroup, Runnable, String) */ @Override public void run() { if (target != null) { target.run(); } }
run方法就很簡單了,就是回調了Runable的run()接口
致使Thread寫的@Overwrite void run() 方法直接是在主線程執行,致使阻塞了主線程。this
到此咱們就知道了,start會使重寫的run方法被虛擬機調用,是在子線程中執行的run方法
而直接調用線程的run方法,他是內部回調了run接口,致使直接執行了Runable.run的重寫內容。至關於直接在主線程中執行。線程
https://www.jianshu.com/p/8c16aeea7e1arest