天天看點

java多線程之啟動,停止線程

    • 線程的啟動
      • 啟動線程的兩種方式
    • 暫停線程
    • 停止線程
      • 停止線程的三種方式
    • 線程的優先級
    • 守護線程

線程的啟動

啟動線程的兩種方式

  • 繼承Thread類

線程代碼:

package com.sun.thread;
public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        System.out.println("我是線程");
    }
}
           

運作類代碼:

package test;
public class TestMyThread {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        System.out.println("我是main函數線程");
    }
           

結果:

我是main函數線程
我是線程
           

可能會問為什麼main函數先執行完了呢,t.start()不是在上面嗎?這是因為線程是個子任務,cpu以不确定的方式,随機的時間來調用線程中的run方法,是以出現這樣的結果,這也說明在使用多線程技術時,代碼的運作結果與代碼的執行順序是無關的。

  • 實作Runnable接口

線程代碼:

package com.sun.thread;
public class MyThreadRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("我是線程");
    }
}
           

運作類代碼:

package test;
public class TestMyThreadRunnable {
    public static void main(String[] args) {
        MyThreadRunnable myThread = new MyThreadRunnable();
        Thread thread = new Thread(myThread);
        thread.start();
        System.out.println("我是main函數線程");
    }
           

使用繼承Thread類建立線程最大的局限,就是java不支援多繼承,是以為了多繼承,完全可以實作Runnable接口的方式,這兩種方法建立的線程工作性質是一樣的

注:在Thread類中,在源碼中可以發現,Thread類實作了Runnable接口。

暫停線程

在java多線程中,可以使用suspend來暫停線程,resume來恢複線程的執行

不推薦使用,因為它和stop方法一樣,都是過期的方法,缺點如下:

  • 獨占

    使用suspend暫停線程極易造成公共同步對象的獨占,暫停線程的時候不會釋放目前鎖,造成其他線程一直等待。。。到天亮還等到下一個天亮。。等到天荒地老

  • 不同步

    使用suspend和resume也容易出現因為線程的暫停而導緻資料不同步的情況出現。

停止線程

停止線程的三種方式

  • 使用退出标記,使線程正常退出

線程代碼:

public class MyThread extends Thread {
    boolean tag = true;

    public void setTag(boolean tag) {
        this.tag = tag;
    }

    @Override
    public void run() {
        int i=;
        super.run();
        while (tag) {
            i++;
            System.out.println("i=" + i);
        }
        System.out.println("我是退出标記的停止狀态!");
    }
}
           

運作類代碼:

public class Test {

    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep();
            thread.setTag(false);
        } catch (InterruptedException e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end!");
    }

}
           

結果:

.
.
.
i=
i=
i=
end!
我是退出标記的停止狀态!
           
  • 使用interrupt方法中斷線程

線程代碼:

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        for (int i = ; i < ; i++) {
            if (this.interrupted()) {
                System.out.println("我是interrupt退出的停止狀态!");
                break;
            }
            System.out.println("i=" + (i + ));
        }
    }
}
           

運作類代碼:

public class Test {

    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep();
            thread.interrupt();
        } catch (InterruptedException e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end!");
    }

}
           

結果:

.
.
.
i=
i=
i=
end!
我是interrupt退出的停止狀态!
           
  • 使用stop方法強行終止線程,但是不推薦使用此方法,這是過期廢棄的方法,可能産生不可預料的結果
使用stop釋放鎖會給資料造成不一緻性的結果,資料可能會造成破壞,最終導緻程式流程錯誤。是以不要學這了,沒用,反正都是過期的方法了。

線程的優先級

  1. 線程的優先級具有繼承性,比如A線程的優先級是8,B繼承A,那麼B的預設優先級也就是8。
  2. 高優先級的線程總是大部分先執行完,但不代表高優先級的線程全部先執行完。
  3. 線程優先級與結果列印順序無關,優先級具有不确定性和随機性。

線程代碼:

public class ThreadA extends Thread {
    private boolean tag = true;
    private int count = ;

    public void setTag(boolean tag) {
        this.tag = tag;
    }

    public int getCount() {
        return count;
    }

    @Override
    public void run() {
        while (tag) {
            count++;
        }
    }

}
           
public class ThreadB extends Thread {
    private boolean tag = true;
    private int count = ;

    public void setTag(boolean tag) {
        this.tag = tag;
    }
    public int getCount() {
        return count;
    }

    @Override
    public void run() {
        while (tag) {
            count++;
        }
    }

}
           

運作類代碼:

public class TestMyThread {
    public static void main(String[] args) {

        try {
            ThreadA a = new ThreadA();
            a.setPriority(Thread.MIN_PRIORITY);
            a.start();

            ThreadB b = new ThreadB();
            b.setPriority(Thread.MAX_PRIORITY);
            b.start();

            Thread.sleep();
            a.setTag(false);
            b.setTag(false);

            System.out.println("a=" + a.getCount());
            System.out.println("b=" + b.getCount());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
           

結果:

a=
b=
           

守護線程

守護線程:當程序中不存在非守護線程的時候,守護線程自動關閉。

通俗的來講,守護線程的作用相當于陪伴,典型的例子就是GC(垃圾回收機制),有程式運作,就有GC

本例中,主線程存在了5秒,則守護線程就守護了5秒

線程代碼:

public class MyThreadDaemon extends Thread {

    @Override
    public void run() {
        int count=;
        while (true) {
            try {
                count++;
                sleep();
                System.out.println(count);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
           

運作類代碼:

public class TestMyThreadDaemon {
    public static void main(String[] args) throws Exception {
        MyThreadDaemon threadDaemon=new MyThreadDaemon();
        threadDaemon.setDaemon(true);
        threadDaemon.start();
        Thread.sleep();
    }
}
           

結果:

此為讀書筆記,權當加強記憶