java 停止某个线程_如何优雅的停止一个正在运行的java线程

线程状态转换图

87f7b0147cba?utm_campaign

线程状态转换图.png

几个容易混淆概念的方法

Thread.sleep()、 Thread.join() 或 Object.wait(),

他们都是阻塞方法并声明抛出 InterruptedException.

当线程调用这些方法进入阻塞状态后, 如果外部调用了interrupt(),

线程进入就绪状态, 并且这些方法抛出InterruptedException异常.

public void Thread.interrupt() // 设置线程的中断状态flag.

public boolean Thread.isInterrupted() // 获取线程的中断状态flag值

public static boolean Thread.interrupted() // 取线程的中断状态flag值,并重置flag值为false.

public final void join() throws InterruptedException //指的是调用者进入阻塞状态, 而不是线程对象进入阻塞状态, 线程对象继续在执行, 不受影响, 看下面的例子.

public static void yield(); //线程从运行状态, 回到就绪状态.

//demo: join()

public class BottomBarManager {

private final Object handlePopupMenuAction(int actionCode, Object... args) {

switch (actionCode) {

case Actions.MenuContainer.DOWNLOAD: // 下载

ThreadTest tt = new ThreadTest();

tt.start();

try {

tt.join(); //当前线程等待tt线程执行完再往下执行

//作用是, 当前的UI线程进入阻塞状态, 直到等tt线程执行完再往下继续执行, tt线程该干什么还干什么, 不受影响.

//千万不要误理解成tt线程进入了阻塞状态.

} catch (InterruptedException e) {

e.printStackTrace();

}

JLog.i();

break;

}

private class ThreadTest extends Thread {

@Override

public void run() {

try {

sleep(100000);

} catch (InterruptedException e) {

e.printStackTrace();

}

JLog.i();

}

}

}

中断线程的最佳实践是: 中断 + 条件变量。

最佳模板:

/**

* @author bruce_sha (bruce-sha.github.io)

* @version 2013-12-23

*/

public class BestPractice extends Thread {

private volatile boolean finished = false; // ① volatile条件变量

public void stopMe() {

finished = true; // ② 发出停止信号

interrupt();

}

@Override

public void run() {

while (!finished) { // ③ 检测条件变量

try {

// do dirty work // ④业务代码

} catch (InterruptedException e) {

if (finished) {

return;

}

continue;

}

}

}

}

当④处的代码阻塞于wait()或sleep()时,线程不能立刻检测到条件变量。因此②处的代码最好同时调用interrupt()方法。

典型的体现是在volley项目中.

// CacheDispatcher.java

public class CacheDispatcher extends Thread {

private volatile boolean mQuit = false;

public void quit() {

mQuit = true;

interrupt();

}

@Override

public void run() {

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

// Make a blocking call to initialize the cache.

mCache.initialize();

while (true) {

try {

// Get a request from the cache triage queue, blocking until

// at least one is available.

final Request> request = mCacheQueue.take(); //****** block方法, it throws InterruptedException;

request.addMarker("cache-queue-take");

// Attempt to retrieve this item from cache.

Cache.Entry entry = mCache.get(request.getCacheKey());

if (entry == null) {

request.addMarker("cache-miss");

// Cache miss; send off to the network dispatcher.

mNetworkQueue.put(request);

continue;

}

// We have a cache hit; parse its data for delivery back to the request.

request.addMarker("cache-hit");

Response> response = null;

try {

response = request.parseNetworkResponse(

new NetworkResponse(entry.data, entry.responseHeaders));

} catch (Exception e) {

mDelivery.postError(request, new ParseError(e));

continue;

} catch (Error error) {

mDelivery.postError(request, new ParseError(error));

continue;

}

request.addMarker("cache-hit-parsed");

} catch (InterruptedException e) {

// We may have been interrupted because it was time to quit.

if (mQuit) {

return;

}

continue;

} catch (OutOfMemoryError error) {

if (mQuit) {

return;

}

continue;

}

}

}

}

在quit()代码里, 设置条件变量, 同时调用interrupt()方法.

以后写线程类时, 参考这个模板写就很优雅和规范.

中断是礼貌地请求另一个线程在它愿意并且方便的时候停止它正在做的事情。

---------DONE.---------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值