1. 程式人生 > >Java多執行緒——實現執行緒的方式以及執行緒的狀態

Java多執行緒——實現執行緒的方式以及執行緒的狀態

什麼是執行緒
執行緒是程序中獨立執行的子任務(程序是受作業系統管理的基本執行單元),在沒有同步的情況下,執行緒的執行是隨機亂序的。
在Java程式設計中,有四種方式去實現多執行緒。

一、實現Runnable介面

Runnable介面中只有一個抽象run()方法,這個方法是執行執行緒的入口,而不是啟動執行緒的入口,啟動執行緒用start()方法,實現這個介面的類就具有了多執行緒的功能了。

public class MyThread implements Runnable {

    private String name;
    public MyThread(String name) {
        this
.name = name; } @Override public void run() { System.out.println("inner thread is running!"); } public String getName() { return name; } public void setName(String name) { this.name = name; }

實現Runnable介面的類,需要使用Thread類的建構函式例項化一個執行緒,下面使用了帶有執行緒名稱的建構函式,第二個引數是執行緒名稱。

public Thread(Runnable target, String name)

執行測試:

    public static void main(String[] args) {
    Thread thread = new Thread(new MyThread("mythread"),"mythread");
        thread.start();
        System.out.println(thread.getName());
        System.out.println("main thread is running!" +Thread.currentThread().getName());
    }

執行結果:

mythread
inner thread is running!
main thread is running!main

二、繼承Thread類

其實繼承Thread類實現多執行緒,本質上也是實現了Runnable介面,因為Thread類實現了Runnable介面。

public class MyThread extends Thread {
    private String some;
    public MyThread(String some) {
        this.some = some;
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" is running!"+"--"+getSome());
    }
    public String getSome() {
        return some;
    }
    public void setSome(String some) {
        this.some = some;
    }
}

實現Thread類,在例項化一個執行緒時,只需要例項化該類。

    public static void main(String[] args) {
        MyThread thread = new MyThread("mythread");
        thread.start();
    System.out.println(Thread.currentThread().getName()+" thread is running!" );
    }

執行結果:

main thread is running!
Thread-0 is running!--mythread

三、繼承TimerTask類

由於TimerTask實現了Runnable介面,因此繼承TimerTask也能夠實現多執行緒。用這種方法,有兩種方式啟動執行緒。

  1. 使用定時器Timer的排程方法schedule()。
  2. 使用Thread的建構函式。
    private static Timer timer = new Timer();

        public static class Mytask extends TimerTask{
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" is running!");
            }
        }
        public static void main(String[] args) {
            //第一種啟動方法
            Mytask mytask = new Mytask();
            timer.schedule(mytask, 1000L);
            //第二種啟動方法
            Thread thread = new Thread(mytask,"mytask");
            thread.start();
        }

執行結果:

mytask is running!
Timer-0 is running!

四、實現Callable介面

Callable介面中只有一個call()方法,該方法具有返回值,並且可以丟擲異常。和Runnable介面有很大的區別,是一種更加高階的實現。

public class CallableService<T> implements Callable<T> {
    private int age;
    public CallableService(int age) {
        super();
        this.age=age;
    }
    @Override
    public T call() throws Exception {
        System.out.println(Thread.currentThread().getName()+" is running!");
        return  (T) ("返回值是:"+age);
    }
}

啟動該執行緒,只需要例項化實現Callable介面的類,然後呼叫call()方法。
執行測試:

    public static void main(String[] args) throws Exception {
        CallableService<String> service = new CallableService<String>(100);
        String t = service.call();
    }

測試結果:

返回值是:100

Callable可以結合Future使用,能夠實現更多的功能。這個在後續的部落格中會講到。

執行緒的狀態

  1. 初始化狀態:即執行緒的新生狀態,使用new出來的執行緒。
  2. 執行狀態:線上程呼叫start()方法後,且沒有發生任何意外和認為的中斷,此時執行緒處於執行狀態。
  3. 阻塞狀態:執行緒呼叫wait(),sleep(),suepend()方法後,將處於該狀態。
  4. 銷燬狀態:執行緒自然的執行結束或呼叫stop()方法銷燬執行緒。

    這裡寫圖片描述

這個圖不是最完善的,在暫停狀態時,當有執行緒呼叫notify()或notifyAll()方法時,阻塞的執行緒會搶佔監視器,先得到監視器的執行緒先執行。