5-10 錯誤停止線程的方法

一、使用被棄用的stop,suspend和resume方法

package threadcoreknpwledge.stopthread;

/**
 * 錯誤的停止方法:使用stop()來停止線程,會導(dǎo)致線程運行到一半突然停止,
 * 沒有辦法完成一個基本單位的操作(一個連隊)。
 * 會造成臟數(shù)據(jù)(有的連隊會多領(lǐng)取或少領(lǐng)取裝備)。
 *  導(dǎo)致對象被破壞,數(shù)據(jù)不一致的情況
 */
public class StopThread implements Runnable{
    
    public static void main(String[] args) {
    
        Thread thread = new Thread(new StopThread());
        thread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.stop();
    }
    
    /**
     * 模擬指揮軍隊:一共5個連隊,每個連隊10人
     * 以連隊為單位發(fā)放武器彈藥,叫到號的士兵前去領(lǐng)取
     */
    @Override
    public void run() {
        for(int i=0;i<5;i++){
            System.out.println("連隊"+i+"開始領(lǐng)取武器");
            for(int j=0;j<10;j++){
                System.out.println(j);
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("連隊"+i+"完成武器領(lǐng)取工作");
        }
    }
}

2,suspend
suspend會讓一個線程掛起,在該線程恢復(fù)之前,是不會釋放鎖的,它是帶著鎖進行休息的,容易造成死鎖,如果沒有其他線程來恢復(fù)它,它就會一直不釋放鎖等待下去。。。

二、 用volatile設(shè)置boolean標(biāo)記位
1,看似可行

package threadcoreknpwledge.stopthread.volatiledemo;

/**
 * 演示volatile的局限:part1 boolean flag似可行
 *
 */
public class WrongWayVolatile implements Runnable {
    
    private volatile boolean canceled = false;
    
    
    @Override
    public void run() {
        int num = 0;
        try {
            while (num <= 10000 && !canceled) {
                if (num % 100 == 0) {
                    System.out.println(num + "是100的倍數(shù)");
                }
                num++;
                Thread.sleep(1);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("結(jié)束任務(wù)");
    }
    
    public static void main(String[] args) throws InterruptedException {
        WrongWayVolatile runnable = new WrongWayVolatile();
        Thread thread = new Thread(runnable);
        thread.start();
        Thread.sleep(5000);
        runnable.canceled = true;
        
    }
}

2,當(dāng)陷入阻塞,volatile是無法停止線程的

package threadcoreknpwledge.stopthread.volatiledemo;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;


/**
 * 演示volatile局限:part2
 * 當(dāng)陷入阻塞,volatile是無法停止線程的,此例中
 * 生產(chǎn)者的生產(chǎn)速度很快,消費者的消費速度很慢
 * 就會出現(xiàn)阻塞隊列滿了的情況,生產(chǎn)者就阻塞了
 *
 * 為什么這些阻塞方法都加上了throw InterruptedException,
 * 是想讓它們在阻塞的時候也能夠響應(yīng)(通過拋異常的方式響應(yīng))接收到的中斷信號。
 */
public class WrongWayVolatileCantStop {
    
    public static void main(String[] args) throws InterruptedException {
        ArrayBlockingQueue storage = new ArrayBlockingQueue(10);
        
        Producer producer = new Producer(storage);
        Thread producerThread = new Thread(producer);
        producerThread.start();
        Thread.sleep(1000);
        Consumer consumer = new Consumer(storage);
        while (consumer.needMoreNums()) {
            //consumer still need number
            System.out.println(consumer.storage.take() + "被消費了");
            Thread.sleep(100);
        }
        //consumer no need number any more
        System.out.println("消費不需要更多數(shù)據(jù)了");
        //一旦消費者不需要更多數(shù)據(jù),就應(yīng)該讓生產(chǎn)者不再生產(chǎn)數(shù)據(jù)。
        //但是實際情況,如果Producer被阻塞了,是無法響應(yīng)這個producer.canceled
        producer.canceled = true;
        System.out.println("producer.canceled = " + producer.canceled);
    }
    
    
}

class Producer implements Runnable {
    BlockingQueue storage;
    public volatile boolean canceled = false;
    
    public Producer(BlockingQueue storage) {
        this.storage = storage;
    }
    
    @Override
    public void run() {
        int num = 0;
        try {
            while (num <= 100000 && !canceled) {
                if (num % 100 == 0) {
                    System.out.println(num + "是100的倍數(shù),準(zhǔn)備放到倉庫中。");
                    storage.put(num);//生產(chǎn)者阻塞在這里了
                    System.out.println(num + "是100的倍數(shù),已經(jīng)放到倉庫中。");
                }
                num++;
            }
            System.out.println("canceled = "+canceled);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("生產(chǎn)者結(jié)束運行");
        }
        
    }
}

class Consumer {
    BlockingQueue storage;
    public volatile boolean canceled = false;
    
    public Consumer(BlockingQueue storage) {
        this.storage = storage;
    }
    
    public boolean needMoreNums() {
        if (Math.random() > 0.95) {
            return false;
        }
        return true;
    }
}

java內(nèi)存結(jié)構(gòu)和Java內(nèi)存模型

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容