1、被弃用的stop,suspend和resume方法
stop方法天生不安全,该方法终止所有未结束的方法,包括run方法。当线程被终止,立即释放被它锁住的所有对象的锁。这会导致对象处于一个不一致的状态。当线程要终止另一个线程时,无法知道什么时候调用stop方法是安全的,什么时候导致对象被破坏。所以被弃用了。
与stop不同,suspend不会破坏对象,它可以和resume方法配套使用,但但其还是有很多缺点,比如容易造成死锁等
2、用volatile设置boolean标记位
-
看似可行的使用volatile
// 演示用Volatile的局限:part1 看似可行
public class WrongWayVolatile implements Runnable {
private volatile boolean canceled = false;
@Override
public void run() {
int num = 0;
while (num <= 10000 && !canceled) {
if (num % 100 == 0) {
System.out.println(num + "是100的倍数");
}
num++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
WrongWayVolatile w = new WrongWayVolatile();
Thread thread = new Thread(w);
thread.start();
Thread.sleep(5000);
w.canceled = true;
}
}
-
使用volatile错误的情况
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()) {
System.out.println(consumer.storage.take() + "被消费了");
Thread.sleep(10);
}
System.out.println("消费者不需要更多数据了");
//一旦消费不需要更多的商品了,我们应该让生产者也停下来
//但是实际情况是
producer.canceled = true;
System.out.println(producer.canceled);
}
}
class Producer implements Runnable {
public volatile boolean canceled = false;
BlockingQueue storage;
public Producer(BlockingQueue storage) {
this.storage = storage;
}
@Override
public void run() {
int num = 0;
while (num <= 10000 && !canceled) {
if ( num % 100 == 0) {
try {
storage.put(num);//当storage满了之后,就会停留在这个地方,线程就无法停止了
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(num + "是100的倍数,被放到了仓库中");
}
num++;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer {
BlockingQueue storage;
public Consumer(BlockingQueue storage) {
this.storage = storage;
}
public boolean needMoreNums() {
if (Math.random() > 0.95) {
return false;
}
return true;
}
}
-
使用interrupt解决问题
//用中断来修复刚才的无尽等待的问题
public class WrongWayVolatileFixed {
public static void main(String[] args) throws InterruptedException {
WrongWayVolatileFixed wrongWayVolatileFixed = new WrongWayVolatileFixed();//当我们需要实例化内部类之前我们需要实例化外部类
ArrayBlockingQueue storage = new ArrayBlockingQueue<>(10);
Producer producer = wrongWayVolatileFixed.new Producer(storage);
Thread producerThread = new Thread(producer);
producerThread.start();
Thread.sleep(1000);
Consumer consumer = wrongWayVolatileFixed.new Consumer(storage);
while (consumer.needMoreNums()) {
System.out.println(consumer.storage.take() + "被消费了");
Thread.sleep(10);
}
System.out.println("消费者不需要更多数据了");
producerThread.interrupt();
}
class Producer implements Runnable {
BlockingQueue storage;
public Producer(BlockingQueue storage) {
this.storage = storage;
}
@Override
public void run() {
int num = 0;
try {
while (num <= 10000 && !Thread.currentThread().isInterrupted()) {
if (num % 100 == 0) {
storage.put(num);
System.out.println(num + "是100的倍数,被放到了仓库中");
}
num++;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("生产者结束运行");
}
}
}
class Consumer {
BlockingQueue storage;
public Consumer(BlockingQueue storage) {
this.storage = storage;
}
public boolean needMoreNums() {
if (Math.random() > 0.95) {
return false;
}
return true;
}
}
}
主要是将生产者类的中的while进行了更改 将 while (num <= 10000 && !canceled)更改为while (num <= 10000 && !Thread.currentThread().isInterrupted())



