話說 線程建立&啓動&中止

線程建立&啓動&中止

線程啊是個好東西,可是平時工做不多本身建立線程,因此一些基礎的操做可能就不容易記起來,這篇文章常看看有益身心健康java

1. 建立
public class TestDeamon {
    public static void main(String[] args) {
        // lambda 表達式
        Thread t1 = new Thread(()->System.out.println("這是一個線程01!"));
        Thread t2 = new Thread(()->{
            System.out.println("這是一個線程02!");
        });
        // 匿名內部類
        Thread t3 = new Thread(){
            @Override
            public void run() {
                System.out.println("這是一個線程03!");
            }
        };
        // 繼承Thread
        Thread t4 =new MyThread04();

        // 實現Runnable 參數是Runnable
        Thread t5 = new Thread(new MyRunnable());

        // 時效內
        // 啓動線程
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}

/**
 * 繼承Thread
 * public class Thread implements Runnable
 * thread是實現了Runnable接口
 */
class MyThread04 extends  Thread{
    @Override
    public void run() {
        System.out.println("這是一個線程04!");
    }
}

/**
 * 實現Runnable
 */
class MyRunnable implements   Runnable{
    @Override
    public void run() {
        System.out.println("這是一個線程05!");
    }
}
2. 啓動
// 啓動線程
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
輸出:
這是一個線程01!
這是一個線程02!
這是一個線程03!
這是一個線程04!
這是一個線程05!

線程啓動以後就會執行run方法ide

3. 中止線程/中斷
3.1. 線程執行完 本身結束

執行完for循環 自動結束測試

// lambda 表達式
        Thread t1 = new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try{
                    Thread.sleep(1000);
                    System.out.println("===");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
3.2. stop 被廢棄了

stop已經被廢棄,stop太粗暴,不溫柔,因此沒人喜歡..spa

// lambda 表達式
Thread t1 = new Thread(()->{
    for (;;) {
        try{
            Thread.sleep(1000);
            System.out.println("===");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});
t1.start();
// 10秒後 中止
Thread.sleep(10000);
// 中止
t1.stop();

很容易產生數據不一致 由於某一個事務或者一塊代碼沒執行完的時候 就有可能被幹掉 線程

舉個例子:code

// lambda 表達式
Thread t1 = new Thread(()->{
    System.out.println("對象去洗澡了");
    try{
        System.out.println("鑽被窩等着...");
        Thread.sleep(10000);
        System.out.println("洗白白 開小會");
    } catch (Exception e) {
        e.printStackTrace();
    }
});

t1.start();
// 10秒後 中止
Thread.sleep(5000);
// 中止
t1.stop();

結果:
對象去洗澡了
鑽被窩等着...
    
能夠看到哈,你等了半天,還沒開始開小會就被打斷了 。。
3.3 suspend resume 被廢棄了

suspend 讓線程暫停 對象

resume 讓暫停的線程繼續執行繼承

suspend容易產生死鎖等問題 若是忘記resume或者resume異常 那若是suspend的線程持有鎖的話,就死鎖了接口

public class TestDeamon03 {
    // 鎖  表示對象
    public static Object obj = new Object();
    public static void main(String[] args) throws InterruptedException {

        // lambda 表達式
        Thread t1 = new Thread(()->{
                synchronized (obj){
                   try {
                       System.out.println("我出去打工了 留對象在家");
                       Thread.sleep(10000);
                       System.out.println("我回來了 娶我對象 ");
                   } catch (Exception e) {
                       e.printStackTrace();
                   }
                }
        });

        t1.start();
        // 2秒後 暫停
        Thread.sleep(2000);
        // 暫停
        t1.suspend();
        Thread.sleep(2000);
        // 恢復 
        resumeObj(t1);
    }

    // resume 模擬異常
    static void resumeObj(Thread t){
        int i = 1/0;
        t.resume();
    }
}

你找了個對象,把人家放家裏,說打工1年回來娶,而後你回家途中找了個別人,一塊兒幸福生活了,你對象在家...事務

被你佔用,你又不通知、不釋放

3.4 volatile 結束

volatile(保證內存可見)修飾一個變量 時間可能控制不是很精確 由於volatile修改了以後刷新到內存 在另外一個線程讀取到 仍是須要時間的 雖然很快 可是通常的狀況 都沒什麼問題

public class TestDeamon04 {
    static volatile boolean flag = true;
    public static void main(String[] args) throws InterruptedException {
        // lambda 表達式
        Thread t1 = new Thread(()->{
            int count =0;
            // flag == true 循環   flag==false 中止循環 也就結束線程了
            while (flag) {
                try {
                    Thread.sleep(1);
                    count++;
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            System.out.println("count:"+count);
        });

        t1.start();
        // 1秒後 中止
        Thread.sleep(1000);
        flag = false;
    }
}

屢次輸出結果:
    50五、52五、50七、512 
能夠看到每次輸出結果是不肯定的 ,
這種方式只能保證到達某個條件了就中止線程  
可是不能控制線程準確點中止 
好比你想讓一個線程循環100次就中止 很難準確控制
3.5 interrupt 結束

也算標誌位 可是比volatile高級一點 好比sleep、wait等操做會被中斷

// lambda 表達式
final Thread t1 = new Thread(()->{
    int count =0;
    //
    while (!Thread.interrupted()) {
        try {
            count++;
        } catch (Exception e){
            e.printStackTrace();
        }
    }
    System.out.println("count:"+count);
});

t1.start();
// 1秒後 中止
Thread.sleep(1000);
t1.interrupt();

中斷sleep測試:interrupt會中斷sleep在異常捕獲裏邊break就好了 而標誌位flag是沒法作到的

public class TestDeamon06 {
    static volatile boolean flag = true;
    public static void main(String[] args) throws InterruptedException {
        // lambda 表達式
        final Thread t1 = new Thread(()->{
            //
            while (!Thread.interrupted()) {
                try {
                    Thread.sleep(20000000);
                } catch (Exception e){
                    break;
                }
            }
            System.out.println("interrupted 結束 ");
        });

        // lambda 表達式
        final Thread t2 = new Thread(()->{
            while (flag) {
                try {
                    Thread.sleep(20000000);
                } catch (Exception e){
                    break;
                }
            }
            System.out.println("volatile-結束");
        });

        t1.start();
        t2.start();
        // 1秒後 中止
        Thread.sleep(1000);
        t1.interrupt();
        flag = false;
    }
}

總結:

stop 、suspend resume 已廢棄

volatile標誌位 沒法中斷sleep wait 等操做

interrupt 至關於標誌位可是能夠中斷sleep wait等操做 捕獲InterruptedException異常 進行線程結束

可能還有其餘方式 大多數是基於標誌位的

有問題能夠留言哦,或者公衆號留言(回覆快):
image

相關文章
相關標籤/搜索