【多線程】Java 多線程技能

概念

區分線程和進程

進程——>.exe程序,進程是受系統操作管理的基本單元

線程:可以理解成是在進程中獨立運行的子任務。

 

使用多線程的優點:可以最大限度地利用CPU的空閒時間來處理其他任務

使用多線程也就是在使用異步。

 

使用多線程

實現方式

1.繼承Thread類

public class MyThread extends Thread{

    @Override
    public void run() {
        System.out.println("run方法的打印:"+Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            MyThread myThread = new MyThread();

            myThread.start();
        }
    }
}

 

 

MyThread類中的run 方法比較晚,這就是說明使用多線程技術時,代碼的運行結果與代碼執行順序或調用順序無關

線程是一個子任務,CPU以不確定的方式,或者說是以隨機的時間來調用線程中的run方法.

a.myThread.start(),方法是通知“線程規劃器”此線程已經準備就緒,等待調用線程對象的run()方法。

b.myThread.run()就不是異步執行了,而是同步,那麼此此線程對象並不是交給“線程規劃器”處理,而是由main主線程來調用run()方法,也就是必須等run()方法中的代碼執行後纔可以執行後面的代碼。

 

 

2.實現Runnable接口

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("運行中!");
    }


    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
        System.out.println("運行結束!");
    }
}

其中Thread類實現了Runnable接口,Java語言的特點就是單繼承,所以爲了支持多繼承,完全可以實現Runnable接口的方法

 

Thead.java類也實現了Runnalbe接口

那也就意味着構造函數Thead(Runnable targer) 不光可以傳入Runnable接口的對象,還可以傳入一個Thread 類的對象,這樣做完全可以將一個Thread對象中的run方法交由其他線程調用

 

 

3.isAlive()

方法是判斷當前的線程是否處於活動狀態

什麼是活動狀態,就是線程已經啓動且尚未終止。線程處於正在運行或者準備開始運行的狀態,就認爲線程是“存活”的。

 

4.sleep()

 

方法sleep()的作用就是在指定的毫秒數內讓當前“正在執行的線程”休眠(暫停這個線程)。

這個正在執行的線程是指this.currentThread()返回的線程。

Thread.sleep(2000);

 

5.停止線程

在Java 中有三種方法可以終止正在運行的線程

  • 1.使用推出標緻,是線程正常退出,也就是當run方法完成後線程終止。
  • 2.使用stop方法強行終止線程,但是不推薦這個方法,因爲stop和suspend及resume一樣,都是作廢的方法,使用他們可能產生不可預料的結果。
  • 3.使用interrupt

 

1.this.interrupted();測試當前線程是否已經是中斷狀態,執行後具有將狀態標誌置清除爲false的功能

2.this.isInterrupted():測試線程Thread對象是否已經是中斷狀態,但不清除標誌。

能停止的線程——異常法

 

public class ExceptionThread extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            for (int i = 0; i < 5000000; i++) {
                if (this.interrupted()) {
                    System.out.println("已經是停止狀態了!我要退出了!");
                    throw new InterruptedException();
                }
                System.out.println("i=" + (i + 1));
            }
            System.out.println("我再for下面!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }


}

 

public class Run {
    public static void main(String[] args) {
        ExceptionThread exceptionThread = new ExceptionThread();
        exceptionThread.start();

        try {
            Thread.sleep(1000);
            exceptionThread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

運行結果如下

 

在沉睡中停止

 

a.先睡後停止

public class SleepThread extends Thread {
    @Override
    public void run() {
        super.run();

        System.out.println("run begin");

        try {
            Thread.sleep(2000);
            System.out.println("run end");
        } catch (InterruptedException e) {
            System.out.println("在沉睡中被停止!進入catch"+this.isInterrupted());
            e.printStackTrace();
        }

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


    }
}

運行結果

 

b.先停止後睡

public class LastSleepThread extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            for (int i = 0; i < 10000; i++) {
                System.out.println("i=" + (i + 1));
            }
            System.out.println("run begin");
            Thread.sleep(200000);
            System.out.println("run end");
        } catch (InterruptedException e) {
            System.out.println("先停止,在遇到了sleep! 進入catch!");
            e.printStackTrace();
        }
    }
}
public class LastSleepRun {
    public static void main(String[] args) {
        try {
            LastSleepThread lastSleepThread = new LastSleepThread();
            lastSleepThread.start();
            lastSleepThread.interrupt();
            System.out.println("end");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

能停止的線程——暴力停止

使用stop()方法停止線程

stop()已經作廢,因爲如果強制讓線程停止則有可能使一些請理性的工作得不到完成。另外一個情況就是對鎖定的對象進行了“解鎖”,導致數據得不到同步的處理,出現數據不一致的問題。

使用return停止線程

public class ReturnThread extends Thread {

    @Override
    public void run() {
        while (true){
            if(this.isInterrupted()){
                System.out.println("停止了!");
                return;
            }
            System.out.println("timer="+System.currentTimeMillis());
        }

    }
}
public class ReturnRun {

    public static void main(String[] args) {
        try {
            ReturnThread returnThread = new ReturnThread();
            returnThread.start();
            Thread.sleep(2000);
            returnThread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

6.暫停線程

暫停線程意味着此線程還可以恢復運行。在java中使用suspend()方法暫停線程,使用resume()方法恢復線程的執行。

suspend與resume方法的缺點——獨佔,極易造成公共的同步對象的獨佔,使得其他線程無法訪問公共同步對象。

 

7.yield方法

yield()方法的作用是放棄當前的CPU資源,將它讓給其他的任務去佔用CPU執行時間。當放棄的時間不確定,有可能剛剛放棄,馬上又獲得CPU時間片。

8.線程的優先級

使用線程的優先級使用setPriority()方法。

在Java中,線程的優先級分爲1-10這10個等級。

線程優先級的繼承特性。

線程的優先級具有繼承性,比如A線程啓動B線程,則B線程的優先級與A是一樣的。

優先級具有隨機性。

9.守護線程

java線程分爲兩種線程,一種是用戶線程,另外一種是守護線程。

什麼是守護線程?守護線程是一種特殊的線程,他的特性有陪伴的意義,當進程中不存在非守護線程了,則守護線程自動銷燬。

典型的守護線程就是垃圾回收線程。

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