美文网首页
5-10 错误停止线程的方法

5-10 错误停止线程的方法

作者: 西西_20f6 | 来源:发表于2020-07-11 21:14 被阅读0次

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

package threadcoreknpwledge.stopthread;

/**
 * 错误的停止方法:使用stop()来停止线程,会导致线程运行到一半突然停止,
 * 没有办法完成一个基本单位的操作(一个连队)。
 * 会造成脏数据(有的连队会多领取或少领取装备)。
 *  导致对象被破坏,数据不一致的情况
 */
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人
     * 以连队为单位发放武器弹药,叫到号的士兵前去领取
     */
    @Override
    public void run() {
        for(int i=0;i<5;i++){
            System.out.println("连队"+i+"开始领取武器");
            for(int j=0;j<10;j++){
                System.out.println(j);
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("连队"+i+"完成武器领取工作");
        }
    }
}

2,suspend
suspend会让一个线程挂起,在该线程恢复之前,是不会释放锁的,它是带着锁进行休息的,容易造成死锁,如果没有其他线程来恢复它,它就会一直不释放锁等待下去。。。

二、 用volatile设置boolean标记位
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的倍数");
                }
                num++;
                Thread.sleep(1);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束任务");
    }
    
    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,当陷入阻塞,volatile是无法停止线程的

package threadcoreknpwledge.stopthread.volatiledemo;

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


/**
 * 演示volatile局限:part2
 * 当陷入阻塞,volatile是无法停止线程的,此例中
 * 生产者的生产速度很快,消费者的消费速度很慢
 * 就会出现阻塞队列满了的情况,生产者就阻塞了
 *
 * 为什么这些阻塞方法都加上了throw InterruptedException,
 * 是想让它们在阻塞的时候也能够响应(通过抛异常的方式响应)接收到的中断信号。
 */
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("消费不需要更多数据了");
        //一旦消费者不需要更多数据,就应该让生产者不再生产数据。
        //但是实际情况,如果Producer被阻塞了,是无法响应这个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的倍数,准备放到仓库中。");
                    storage.put(num);//生产者阻塞在这里了
                    System.out.println(num + "是100的倍数,已经放到仓库中。");
                }
                num++;
            }
            System.out.println("canceled = "+canceled);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("生产者结束运行");
        }
        
    }
}

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内存结构和Java内存模型

相关文章

网友评论

      本文标题:5-10 错误停止线程的方法

      本文链接:https://www.haomeiwen.com/subject/zuphcktx.html