在java中可有兩種方式實現多線程,一種是繼承Thread類,一種是實現Runnable接口;Thread類是在java.lang包中定義的。一個類只要繼承了Thread類同時覆寫了本類中的run()方法就能夠實現多線程操做了,可是一個類只能繼承一個父類,這是此方法的侷限。java
可是實際在使用過程你會發現一些令你迷惑的問題,就來看下吧下面的代碼:多線程
public class SeThread implements Runnable { private int i; @Override public void run() { for (; i < 20; i++) { System.out.println(Thread.currentThread().getName() + " i= "+ i); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { if (i == 20) { SeThread st = new SeThread(); new Thread(st, "線程1").start(); new Thread(st, "線程2").start(); } } } }
能夠看到,st是一個Runnable接口實現類的對象,可是卻被兩個線程做爲參數,啊啊。這個打印結果是什麼玩意??ide
看到這或許你已經猜到了,這個是兩個Thread的外殼下竟然是同一顆跳到的Runnable心,那麼仍是看下Thread的實現吧。this
public class Thread implements Runnable { public synchronized void start() { 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 */ } } } private native void start0(); @Override public void run() { if (target != null) { target.run(); } } //…… }
其實,Thread就是Runnable實現類,在調用start過程當中,咱們能夠知道它實現調用的是一個start0()這個本地方法,這個從咱們之前開發用的方法可知,確定是在CPU資源分配過程當中的某個時機調用了Thread的run()方法了,而run()方法實現的執行體就是傳入的Runnable對象的runnable。.net
因此兩個Thread的執行體,就是同一個runnale對象了,這個看上去是兩個線程,可實際上只有一個執行體那就是st對象啦,打印結果確定是如上圖看到的那樣了。線程
其實這個打印有兩個0,可知線程未同步,咱們能夠在處理打印這個方法作個同步修飾synchronized,這樣就能夠正確的打印從0到99啦。code