API提供的方法存在的問題
public class StopThread3 {
private static Object lock = new Object();
private static int number = 0;
static int tmp = 0;
public static void main(String[] args) {
ThreadOne t1 = new ThreadOne();
t1.start();
ThreadTwo t2 = new ThreadTwo();
t2.start();
t1.stop();
t2.stop();
}
static class ThreadOne extends Thread {
public void run() {
add();
}
private void add() {
while (true) {
synchronized (lock) {
System.out.println("number=" + number);
tmp++;
number++;
}
}
}
}
static class ThreadTwo extends Thread {
public void run() {
add();
}
private void add() {
while (true) {
synchronized (lock) {
System.out.println("number=" + number);
tmp++;
number++;
}
}
}
}
}
其中的一次輸出:
number=347
number=348
number=348
number=349
number=350
替代stop的方法
class MyThread extends Thread {
volatile boolean flag = false;
public void stopThread(){
flag = true;
}
@Override
public void run() {
while (flag) {
process();
}
}
private void process() {
...
}
}
flag必須使用
volatile
修飾侈净,或者訪問flag的方法是同步的尊勿,如下:
class MyThread extends Thread {
boolean flag = false;
public synchronized void stopThread(){
flag = true;
}
@Override
public void run() {
while (flag) {
process();
}
}
private void process() {
...
}
}
這個是很常用的方法但是在某些情況下并不適用。
在上面的荔枝中如果process()
是一個很耗時的操作畜侦,當在別的線程中修改了flag并不能停止線程。這時需要用到Thread.interrupt
躯保。
使用 Thread.interrupt
class MyThread extends Thread {
public void stopThread() {
interrupt();
}
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
process();
}
System.out.println("...end...");
}
private void process() {
System.out.println("---process---");
try {
Thread.sleep(1000 * 1000);
} catch (InterruptedException ex) {
System.out.println("InterruptedException");
}
}
}
Thread.interrupt
只能中斷響應(yīng)InterruptedException
的線程旋膳。如果將上例中的process()
改為下面的形式,將不能終止線程的執(zhí)行途事。
private void process() {
System.out.println("---process---");
while (true) {}
}
Override interrupt()
對于不能響應(yīng)
InterruptedException
的情況可以針對具體的情況验懊,重寫interrupt()
方法。如果我們試圖讀取一個已經(jīng)關(guān)閉的InputStream
時尸变,會產(chǎn)生一個stream is closed
的錯誤义图,當我們在interrupt
方法中關(guān)閉了InputStream
,讀取這個InputStream
的線程就會中斷。記渍倮谩:使用此方法不能在catch
進行可以中終止線程的操作,如printStackTrace()
碱工。
public class StopThread2 {
public static void main(String[] args) {
new StopThread2().test();
}
private void test() {
final MyThread myThread = new MyThread();
myThread.start();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1200);
} catch (InterruptedException ex) {
}
myThread.stopThread();
}
}).start();
}
class MyThread extends Thread {
private URLConnection conn;
private volatile InputStream in;
public void stopThread() {
interrupt();
}
@Override
public void interrupt() {
try {
in.close();
} catch (IOException ex) {
System.out.println("IOException:" + ex.getMessage());
}
super.interrupt();
}
@Override
public void run() {
try {
URL url = new URL("http://new.hellopojo.site/AndroidDev");
conn = url.openConnection();
in = conn.getInputStream();
process(in);
System.out.println("...end...");
} catch (Exception ex) {
System.out.println("---" + ex.getStackTrace());
}
}
private void process(InputStream in) {
try {
System.out.println("---process---");
InputStreamReader isr = new InputStreamReader(in, "utf-8");
BufferedReader reader = new BufferedReader(isr);
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println("" + line);
}
} catch (IOException ex) {
System.out.println("IOException:" + ex.getMessage());
}
}
}
}