一、使用被弃用的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内存模型
网友评论