java 停止一个线程_Java如何停止一个线程

本文详细介绍了Java中如何控制线程的执行,包括正常结束线程、通过设置标志位以及中断机制。讨论了线程在阻塞状态下如何响应中断,展示了Thread类的interrupt()、isInterrupted()和interrupted()方法的作用,并提供了示例代码说明如何在循环中检查中断状态以优雅地终止线程。此外,还提到了使用Future的cancel()方法来停止线程的执行。
摘要由CSDN通过智能技术生成

线程正常执行完毕,正常结束。

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);来停止线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值