1. 程式人生 > >暫停執行緒(菜鳥玩執行緒)

暫停執行緒(菜鳥玩執行緒)

暫停執行緒

暫停執行緒,即執行緒還可以恢復執行。

Java多執行緒中,可以使用suspend()方法停止執行緒,使用resume()方法恢復執行緒的執行。

suspend與resume方法的使用

直接上程式碼:

自定義執行緒類

package com.thread9;

public class MyThread extends Thread {
    private long i;

    public long getI() {
        return i;
    }

    public void setI(long i) {
        this.i = i;
    }
@Override public void run() { while (true) { i++; } } }

啟動類

package com.thread9;

public class Run {
    public static void main(String[] args) {
        try {
            MyThread myThread = new MyThread();
            myThread.start();
            Thread.
sleep(5000); //A段 myThread.suspend(); System.out.println("A = " + System.currentTimeMillis() + " , i =" + myThread.getI()); Thread.sleep(5000); System.out.println("A = " + System.currentTimeMillis() + " , i =" + myThread.getI()); //B段 myThread.
resume(); Thread.sleep(5000); System.out.println("醒了"); //C段 myThread.suspend(); System.out.println("B = " + System.currentTimeMillis() + " , i =" + myThread.getI()); Thread.sleep(5000); System.out.println("B = " + System.currentTimeMillis() + " , i =" + myThread.getI()); } catch (InterruptedException e) { e.printStackTrace(); } } }

執行結果

A = 1541211738334 , i =3401982429
A = 1541211743334 , i =3401982429
醒了
B = 1541211748334 , i =6686269724
B = 1541211753334 , i =6686269724

結論

從輸出結果中看,主要看i變數,執行緒的確貝暫停了,而且還可以恢復成執行狀態。

但是執行起來,執行緒結束不了????

suspend與resume方法的缺點——獨佔

如果使用不當,極容易早晨公共的同步物件的獨佔,使得其他執行緒無法訪問公共同步物件。

程式碼例項如下:

自定義執行緒類

package com.thread10;

public class MyThread extends Thread {
    private long i;

    public long getI() {
        return i;
    }

    public void setI(long i) {
        this.i = i;
    }
    @Override
    public void run() {
        while (true) {
            i++;
            System.out.println(i);
        }
    }
}

啟動類

package com.thread10;

public class Run {
    public static void main(String[] args) {
        try {
            MyThread myThread = new MyThread();
            myThread.start();
            Thread.sleep(1000);
            myThread.suspend();
            System.out.println("main end");

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

執行結果

207532
207533
207534
207535
207536
207537
207538
207539
207540
207541

//此處暫停,不繼續輸出

結論

出現這種情況得原因是,當程式執行到println()方法內部停止時,同步鎖未被釋放。

導致當前PrintStream物件得println()方法一直呈“暫停”狀態,並且“鎖未釋放”,而main()方法中的程式碼

System.out.println("main end");

遲遲不能執行列印。

    public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }

suspend與resume方法的缺點——不同步

在使用suspend和resume方法時也容易出現因為執行緒的暫停而導致資料不同步的情況,如下:

自定義共享變數類

package com.fiberhome.thread11;

public class MyObject {
    private String username = "1";
    private String password = "11";

    public void setValue(String u, String p) {
        this.username = u;
        if (Thread.currentThread().getName().equals("a")) {
            System.out.println("停止a執行緒!");
            Thread.currentThread().suspend(); //執行緒停止
        }
        this.password = p;
    }

    public void printUsernamePassword() {
        System.out.println(username + " " + password);
    }
}

啟動類

package com.fiberhome.thread11;

public class Run {
    public static void main(String[] args) throws InterruptedException {
        //共享變數
        final MyObject myObject = new MyObject();

        //執行緒1
        Thread thread1 = new Thread() {
            @Override
            public void run() {
                myObject.setValue("a", "aa");
            }
        };
        thread1.setName("a");
        thread1.start();
        Thread.sleep(500);

        //執行緒2
        Thread thread2 = new Thread() {
            @Override
            public void run() {
                myObject.printUsernamePassword();
            }
        };
        thread2.start();
    }
}

執行結果

停止a執行緒!
a 11

結論

從輸出結果看,共享物件資料沒有同步。如果同步,輸出結果應該為 a aa