相信Thread對我們來說並不陌生,學java的時候都是入門的東西,我們一般使用thread都是new一個線程,然後調用start方法啓動,使用start方法才真正實現了多線程運行,因爲這個時候不用等待我們的run方法執行完成就可以繼續執行下面的代碼,這才叫多線程嘛!因爲thread線程有5種狀態,創建-就緒-運行-阻塞-死亡這五種,那麼我們的start方法呢就是就緒這一步,因爲這個時候我們的線程並沒有立即的執行,而是得等待,等到我們的cpu有空閒的時候,纔會執行線程裏面的run方法,等run方法執行完了,線程就結束了。
那麼我們直接使用thread執行run方法會咋樣呢?因爲run方法是thread裏面的一個普通的方法,所以我們直接調用run方法,這個時候它是會運行在我們的主線程中的,因爲這個時候我們的程序中只有主線程一個線程,所以如果有兩個線程,都是直接調用的run方法,那麼他們的執行順序一定是順序執行,所以這樣並沒有做到多線程的這種目的。
public class ThreadTest {
public static void main(String[] args) {
new Thread(new printA()).start();
new Thread(new printB()).start();
}
}
class printA implements Runnable{
@Override
public void run() {
try {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"-->"+"A");
Thread.sleep(200);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
class printB implements Runnable{
@Override
public void run() {
try {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"-->"+"B");
Thread.sleep(200);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
Thread-0–>A
Thread-1–>B
Thread-1–>B
Thread-0–>A
Thread-0–>A
Thread-1–>B
Thread-0–>A
Thread-1–>B
Thread-0–>A
Thread-1–>B
Thread-0–>A
Thread-1–>B
Thread-0–>A
Thread-1–>B
我們可以發現,創建了新的線程Thread-0和Thread-1,爲了更加清楚的看到兩個線程是不是並行的執行,在打印的時候,讓線程阻塞了一會,可以看到兩個線程是並行執行的。那麼直接調用run()方法會怎麼樣呢?
public class ThreadTest {
public static void main(String[] args) {
new Thread(new printA()).run();
new Thread(new printB()).run();
}
}
class printA implements Runnable{
@Override
public void run() {
try {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"-->"+"A");
Thread.sleep(200);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
class printB implements Runnable{
@Override
public void run() {
try {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"-->"+"B");
Thread.sleep(200);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
main–>A
main–>A
main–>A
main–>A
main–>A
main–>A
main–>A
main–>A
main–>A
main–>A
main–>B
main–>B
main–>B
main–>B
main–>B
main–>B
main–>B
main–>B
可以發現,直接調用run方法程序是順序執行的,只有一個主線程main
這不就是直接調用一個對象的一個方法嗎,自然是順序執行的,那麼爲什麼調用start()方法是創建新的線程呢?
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();
/* 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 {
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()這個方法,這個方法調用了底層,因此可以創建一個新的線程。
爲什麼創建的線程可以調用傳入的Runnable子類的run方法呢?
/**
* 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();
}
}
target是啥呢,其實就是傳入Runnable子類對象的引用
/* What will be run. */
private Runnable target;