java kill 线程_Java如何停止线程,确定你知道的都是正确的么?

回想当年刚开始做Java开发的时候,如何停止线程运行可是难倒了一批人,停止线程的方法众说纷纭:

1. 调用Thread.stop() :

Thread thread = new Thread(){

@Override

public void run() {

for (int i=0; i < 999 && !isCanceled; i++) {

System.out.println("哈哈,我还没死...");

}

}

};

thread.start();

// kill you now

thread.stop();

点评: 不用多说,直接拉出去斩了

2. 线程外面定义boolean变量标识为是否已经取消,线程里每个循环地方加判断,变量变成了取消则停止循环:

private volatile boolean isCanceled = false;

new Thread(){

@Override

public void run() {

for (int i=0; i < 999 && !isCanceled; i++) {

System.out.println("哈哈,我还没死...");

}

}

}.start();

// kill thread

isCanceled = true;

点评: 太片面,线程里Thread.sleep(999999)取消不了的

3. 通过调用interrupt() :

Thread thread = new Thread(){

@Override

public void run() {

sleep(99999);

System.out.println("刚睡醒,我还没死!!!");

}

};

thread.start();

// kill you now

thread.interrupt();

点评:也是太片面,for循环取消不了

4. 以上方案意思是有那么一点了,只是零零碎碎,如何将两个方案结合是今天的第一个话题。

在Thread内提供了一个方法叫interrupted(), 其返回值即告知是否线程被interrupt()执行过,简单说:无需自己定义boolean变量,可以用它代替,如果线程能被interrupt()而停止正好,如果是内部循环操作可以用它作为循环停止的条件:

Thread thread = new Thread(){

@Override

public void run() {

for (int i=0; i < 999 && !Thread.interrupted(); i++) {

System.out.println("哈哈,我还没死...");

}

}

};

其实,还有一种情况是停止不了的,类似socket/http通信这种不能被interrputted的情况,当然也有巧妙的办法:重载Thread的interrput()方法:

// 重载interrupt 通过关闭socket起到关闭线程的作用

@Override

public void interrupt() {

try {

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

今天的第二个话题是,使用单个线程的情况在项目中极少,很多情况使用线程池托管的,那么线程池里如何停止某个task呢?

JDK5提供了ExecuteService,并通过Executors提供了多个候选的线程池选择方案,ExecutorService提交task有两种方式:execute()和submit(), 我们这里对submit()比较感兴趣,因为其中submit()会返回Feature,不管submit的是 Runnable还是Callable都会有Feature返回:

public interface ExecutorService extends Executor {

/**

* Submits a value-returning task for execution and returns a

* Future representing the pending results of the task. The

* Future's {@code get} method will return the task's result upon

* successful completion.

*

*

* If you would like to immediately block waiting

* for a task, you can use constructions of the form

* {@code result = exec.submit(aCallable).get();}

*

*

Note: The {@link Executors} class includes a set of methods

* that can convert some other common closure-like objects,

* for example, {@link java.security.PrivilegedAction} to

* {@link Callable} form so they can be submitted.

*

* @param task the task to submit

* @param the type of the task's result

* @return a Future representing pending completion of the task

* @throws RejectedExecutionException if the task cannot be

* scheduled for execution

* @throws NullPointerException if the task is null

*/

Future submit(Callable task);

/**

* Submits a Runnable task for execution and returns a Future

* representing that task. The Future's {@code get} method will

* return {@code null} upon successful completion.

*

* @param task the task to submit

* @return a Future representing pending completion of the task

* @throws RejectedExecutionException if the task cannot be

* scheduled for execution

* @throws NullPointerException if the task is null

*/

Future> submit(Runnable task);

/**

* Submits a Runnable task for execution and returns a Future

* representing that task. The Future's {@code get} method will

* return the given result upon successful completion.

*

* @param task the task to submit

* @param result the result to return

* @param the type of the result

* @return a Future representing pending completion of the task

* @throws RejectedExecutionException if the task cannot be

* scheduled for execution

* @throws NullPointerException if the task is null

*/

Future submit(Runnable task, T result);

}

Feature对象提供了一系列API,如:

cancel(boolean mayInterruptIfRunning) ;

isCanceled();

get();

get(long timeout, TimeUnit unit);

isDone()

看到第一个API,很是让人兴奋,难倒这真的可以一步到位?但很不好意思,依然不行,其实跟第一个话题的原理一摸一样,如果内部有阻塞线程的操作会因此而退出,如: wait(), join(), sleep() 等,但是遇到IO阻塞操作,比如进行socket通信,仅仅通过调用cancel(true)是不行的,不过可以重载interrupt() 关闭socket即可, 遇到大量循环也要通过Thread.interrupted()作为循环结束的条件:

class Task extends Thread{

private Socket socket;

public Task(){

// init socket

}

// 重载interrupt 通过关闭socket起到关闭线程的作用

@Override

public void interrupt() {

try {

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

public void func () {

ExecutorService timer = Executors.newCachedThreadPool();

Future> future = timer.submit(new Task());

future.cancel(true);

}

好了,夜深了...回忆到此结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值