java線程(一)

java線程(一)

線程的生命週期及五種基本狀態

這裏寫圖片描述新建狀態(New):當線程對象對創建後,即進入了新建狀態,如:Thread t = new MyThread();

就緒狀態(Runnable):當調用線程對象的start()方法(t.start();),線程即進入就緒狀態。處於就緒狀態的線程,只是說明此線程已經做好了準備,隨時等待CPU調度執行,並不是說執行了t.start()此線程立即就會執行;

運行狀態(Running):當CPU開始調度處於就緒狀態的線程時,此時線程才得以真正執行,即進入到運行狀態。注:就 緒狀態是進入到運行狀態的唯一入口,也就是說,線程要想進入運行狀態執行,首先必須處於就緒狀態中;

阻塞狀態(Blocked):處於運行狀態中的線程由於某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才 有機會再次被CPU調用以進入到運行狀態。根據阻塞產生的原因不同,阻塞狀態又可以分爲三種:

  1. 等待阻塞:運行狀態中的線程執行wait()方法,使本線程進入到等待阻塞狀態;

  2. 同步阻塞 – 線程在獲取synchronized同步鎖失敗(因爲鎖被其它線程所佔用),它會進入同步阻塞狀態;

  3. 其他阻塞 – 通過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。

死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。

實現線程的基本方法

實現runnable接口

package cn.sc.thread;

public class BaseThread {
    public static void main(String[] args) {
        Runnable myRunnable = new MyRunnable();
        myRunnable.run();
        new Thread(myRunnable).start();
    }
}


class MyRunnable implements Runnable{
    public void run() {
        System.out.println(Thread.currentThread().getName()+" my runnable");
    }
}

運行之後輸出

main my runnable
Thread-0 my runnable

繼承Thread

public class BaseThread {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myRunnable.run();
        myThread.start();
    }
}

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+ " my thread");
    }
}

運行後輸出

main my thread
Thread-0 my thread

解析

可以看到,如果直接調用run方法,並沒有啓動新的線程,而是繼續使用主線程運行run方法。直接執行run方法就和實現一個普通類一樣。
查看Thread類的源碼可以得知

   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) {

            }
        }
    }

    private native void start0();

通過navtive的方法調用jre的本地方法庫,操作cpu開啓了新的線程。
通過new Thread()之後線程進入new狀態
通過thread.start()之後將新建的線程從new狀態進入runnable狀態

實現Callable

public class ThreadTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        MyCallable myCallable = new MyCallable();
        FutureTask<String> stringFutureTask = new FutureTask<>(myCallable);
        Thread thread = new Thread(stringFutureTask);
        thread.start();
        String s = stringFutureTask.get();
        System.out.println(s);
    }
}

class MyCallable implements Callable<String>{
    @Override
    public String call() throws Exception {
        System.out.println(Thread.currentThread().getName()+ " my callable");
        return "myCallable";
    }
}

輸出

Thread-0 my callable
myCallable

幾個例子

通過runnable創建thread,會執行誰

package cn.sc.thread;

public class ThreadTest {

    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName());
        MyRunnable myRunnable = new MyRunnable();
        MyThread myThread = new MyThread(myRunnable);
        myThread.start();
    }
}

class MyRunnable implements Runnable{
    public void run() {
        System.out.println(Thread.currentThread().getName()+" my runnable");
    }
}

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+ " my thread");
    }
}

運行結果爲

main
Thread-0 my thread

啓動線程後,線程的執行體爲run方法。
爲什麼調用了MyThread的run方法而沒有調用MyRunnable的run方法呢?
Thread類實現了Runnable接口

 @Override
  public void run() {
      if (target != null) {
          target.run();
      }
  }

這個target就是新建線程之後傳進去的MyRunnable對象,但是爲什麼沒有執行呢?
因爲MyThread類重寫了Thread的run方法,因此在執行時由於java的多態特性,就會執行子類的重寫後的run方法了。

同一個thread可以啓動兩次嗎

package cn.sc.thread;

public class ThreadTest {

    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        myThread.start();
    }
}
class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+ " my thread"+i);

        }
    }
}

運行後輸出

Thread-0 my thread0
Thread-0 my thread1
Thread-0 my thread2
Thread-0 my thread3
Thread-0 my thread4
Thread-0 my thread5
Thread-0 my thread6
Thread-0 my thread7
Thread-0 my thread8
Thread-0 my thread9
Exception in thread "main" java.lang.IllegalThreadStateException
    at java.lang.Thread.start(Thread.java:708)
    at cn.sc.thread.ThreadTest.main(ThreadTest.java:10)

同一個線程只能start一次。
如上面所講的,

if (threadStatus != 0)
     throw new IllegalThreadStateException();

start方法將新建的線程從new狀態進入runnable狀態,
第一次start之後,這個線程就進入了runnable狀態了,並修改threadStatus
第二次再start的時候,threadStatus已經不是0了,就會拋出這個錯誤了

參考
http://www.cnblogs.com/lwbqqyumidi/p/3804883.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章