一、使用被棄用的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)存模型