java 停止一个线程_Java如何停止一个线程
線程正常執行完畢,正常結束。
2.監視某些條件,直到某些條件成立,結束線程。
class TestMyThread extends Thread {
private volatile boolean shouldStop;
public TestMyThread(boolean shouldStop) {
this.shouldStop = shouldStop;
}
public void setShouldStop(boolean shouldStop) {
this.shouldStop = shouldStop;
}
@Override
public void run() {
while (!shouldStop) {
System.out.println(getName() + "Thread is running");
}
System.out.println(getName() + "線程退出");
}
}
TestMyThread thread = new TestMyThread(false);
thread.start();
try {
Thread.sleep(1000);
thread.setShouldStop(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
在上面的例子中,如果shouldStop為false,那么線程會一直執行,我們可以在外部調用setShouldStop()方法將shouldStop置為true來結束線程的運行。
上面的方法2存在一個問題:如果線程是阻塞的,則無法結束線程。我們修改一下代碼
class TestMyThread extends Thread {
private volatile boolean shouldStop;
public TestMyThread(boolean shouldStop) {
this.shouldStop = shouldStop;
}
public void setShouldStop(boolean shouldStop) {
this.shouldStop = shouldStop;
}
@Override
public void run() {
while (!shouldStop) {
System.out.println(getName() + "Thread is running");
try {
//讓線程睡眠
sleep(100000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + "線程退出");
}
}
我們讓線程睡眠很長一段時間
TestMyThread thread = new TestMyThread(false);
thread.start();
try {
Thread.sleep(1000);
thread.setShouldStop(true);
System.out.println("setShouldStop true");
} catch (InterruptedException e) {
e.printStackTrace();
}
我們發現,即使我們調用setShouldStop()方法將shouldStop置為true,線程依然不會結束。
使用中斷來中斷一個阻塞的線程
下面是Thread類中斷相關的方法。
Thread的interrupt() 方法。
/**
* 中斷線程
*
*
如果是其他線程中斷當前線程,當前線程的checkAccess()方法會被調用。
* 如果其他線程沒有權限修改當前線程,那么會拋出一個SecurityException。
*
*
如果當前線程是由于Object類的下列方法調用
*{@link Object#wait() wait()},
*{@link Object#wait(long) wait(long)},
*{@link Object#wait(long, int) wait(long, int)}
*或者Thread類的下列方法調用
*{@link #join()}, {@link #join(long)}
*{@link #join(long, int)}
*{@link #sleep(long)}
*{@link #sleep(long, int)}
*而阻塞,那么當前線程的中斷狀態會被清除,并且會收到一個 {@link InterruptedException}.
*
*
如果當前線程是因為在
*{@link java.nio.channels.InterruptibleChannel InterruptibleChannel}
*上的I/O操作而阻塞,那么這個通道會關閉,當前線程的中斷狀態會被置為true。
*同時當前線程會收到一個 {@link java.nio.channels.ClosedByInterruptException}.
*
* 如果當前線程在 {@link java.nio.channels.Selector}上被阻塞了,那么當前線程的
* 中斷狀態會被置為true并且當前線程會從selection operation立即返回,
* 同時可能會帶有一個非0的值。就像是
* selector的 {@link java.nio.channels.Selector#wakeup wakeup} 方法被調用了。
*
*
如果前面的情況都沒有發生,那么當前線程的中斷狀態會被置為true。
*
*
中斷一個死亡的線程不會產生任何影響。
*
* @throws SecurityException 如果當前線程不能被修改
*
* @revised 6.0
* @spec JSR-51
*/
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
Thread的isInterrupted() 方法。
/**
* 檢測當前線程是否被中斷了。這個方法不會影響當前線程的中斷狀態。
*
線程死亡的時候,線程中斷是被忽略的,當前方法會返回false。
*
* @return 如果當前線程被中斷了,返回true。否則返回false。
* @see #interrupted()
* @revised 6.0
*/
public boolean isInterrupted() {
return isInterrupted(false);
}
Thread的interrupted() 方法。注意這個方法是靜態方法。
/**
* 檢測當前線程是否被中斷了。該方法會清除當前線程的中斷狀態。換句話說,
* 如果當前方法被成功調用了兩次,
* 如果第一次返回了true,那么第二次會返回false(除非當前線程在當前方法第一次調用之后清除了中斷狀態和第二次調用之前當前線程被再次中斷了)
*
*
線程在死亡的時候,線程中斷是被忽略的,當前方法會返回false。
*
* @return 如果當前線程被中斷了,返回true。否則返回false。
* @see #isInterrupted()
* @revised 6.0
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
當使用Thread的interrupt()方法時,線程的中斷狀態會被設置為true。
下面的例子啟動了一個線程,循環執行打印一些信息。使用isInterrupted()方法判斷線程是否被中斷,如果是就結束線程。
class MyInterruptedThread extends Thread {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("running");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("InterruptedException occurred");
//拋出InterruptedException后中斷標志被清除,標準做法是再次調用interrupt恢復中斷
Thread.currentThread().interrupt();
}
}
System.out.println("stop");
}
public static void main(String[] args) {
MyInterruptedThread thread = new MyInterruptedThread();
thread.start();
try {
Thread.sleep(2000);
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
在線程啟動后,我們延遲兩秒調用interrupt()方法。對線程調用interrupt()方法,不會真正中斷正在運行的線程,只是發出一個請求,由線程在合適時候結束自己。
注意:如果線程由于調用Thread類的sleep方法而阻塞,那么當前線程的中斷狀態會被清除,并且會收到一個 InterruptedException,所以我們在捕捉到這個異常后需要再次調用interrupt方法恢復中斷。
使用Future的取消功能來停止一個線程
class MyInterruptedThread extends Thread {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("running");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("InterruptedException occurred");
//拋出InterruptedException后中斷標志被清除,標準做法是再次調用interrupt恢復中斷
Thread.currentThread().interrupt();
}
}
System.out.println("stop");
}
}
MyInterruptedThread thread = new MyInterruptedThread();
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future> future = executorService.submit(thread);
try {
future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
System.out.println("thread over time");
} finally {
//取消
future.cancel(true);
}
調用future.cancel(true);來停止線程。
總結
以上是生活随笔為你收集整理的java 停止一个线程_Java如何停止一个线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 传入参数_Java 中方法参数
- 下一篇: java media player_Me