关于JAVA线程停止的思考
2014-12-08 14:34
295 查看
一个好的软件线程通常都是可控制的,开发者不但可以利用多线程来提升软件的效率,以可以HOLD住线程,可以销毁线程,防止线程泄漏。
什么是JAVA的线程停止?
前段时间,我还自认为线程的停止,指的是线程的销毁。如果我停止一个线程,那么这个线程将会被销毁,至于如何销毁,那都是JVM应该考虑的事情,我只需调用对应 的API(比如Thread.interrupt(), Thread.stop(), Thread.destroy())。
后来发现不是那么一回事,JAVA中线程的停止是交给开发者来维护的,不是简简单单的调用了一个接口,线程就不复存在了,且线程所用的资源也都被释放了,如果真是这样,那JVM也真是太强大了。
好的线程停止,是通过响应中断方法来实现的。
那么问题来了,谁有资格去停止线程?
线程的创建者(或者任务的提交者)应该负责来停止线程。当业务上需要中断一批任务时,把消息发送给线程的创建者或者任务的提交者(根据信息专家模式),因为他们持有线程的信息。
一个好的线程写法,应该是提交和任务相分离。如果代码中出现这样的语句:new Thread(Runnable).start()
这是一个糟糕的写法,因为这意味着,创建的线程永远无法被人工的终止,当大量创建这样的线程时,这些线程就相当于无政府主义者,不受约束,一旦产生,将会自生自灭。而且这样 的线程不容易修改,假如工程中有一百个上述代码片段,现在任务要变成同步执行(原先的写法肯定是并发执行),如何?这样改动可能要该100处,这对于维护者或者重构者来说简直就是灾难。
好的写法应该是任务的提交和创建相分离(上面是典型的创建和提交混合在一起了)。
比如如下代码:
public class MyThreadSubmitter implements Executor {
@Override
public void execute(Runnable command) {
Thread thread = new Thread(command);
thread.start();
}
}
当想同步执行时,换一个方式就可以了,只需要改动一处,代码如下:
public class MyThreadSubmitter implements Executor {
@Override
public void execute(Runnable command) {
command.run();
}
}
上面阐述了任务的提交和创建相分离,回归老问题:如何终止一个线程?上面已经简要回答了下:即由程序员来维护线程,在程序员写代码的时候,就要考虑到线程终止,通过响应线程中断信号来实现。而不是交由JVM,任凭JVM来销毁,这样是不符合业务逻辑的。
那么如何来编写响应中断式的线程?这个用一个例子来说明。
public class Task implements Runnable {
@Override
public void run() {
try {
boolean isInterrupt = false;
while (!(isInterrupt = Thread.interrupted())) {
//处理业务逻辑
}
if (isInterrupt) {//相应线程中断
}
} catch (Throwable e) {//防止线程泄漏
e.printStackTrace();
} finally{
//释放资源
}
}
} 如何提交呢?
因为TaskSubmiter是任务的提交者,故TaskSubmiter持有线程的上线文信息,发送停止指令,应发送到该类。stop接口提现了线程的停止。以上就是一个通过响应中断来实现线程停止的简单模型。
什么是JAVA的线程停止?
前段时间,我还自认为线程的停止,指的是线程的销毁。如果我停止一个线程,那么这个线程将会被销毁,至于如何销毁,那都是JVM应该考虑的事情,我只需调用对应 的API(比如Thread.interrupt(), Thread.stop(), Thread.destroy())。
后来发现不是那么一回事,JAVA中线程的停止是交给开发者来维护的,不是简简单单的调用了一个接口,线程就不复存在了,且线程所用的资源也都被释放了,如果真是这样,那JVM也真是太强大了。
好的线程停止,是通过响应中断方法来实现的。
那么问题来了,谁有资格去停止线程?
线程的创建者(或者任务的提交者)应该负责来停止线程。当业务上需要中断一批任务时,把消息发送给线程的创建者或者任务的提交者(根据信息专家模式),因为他们持有线程的信息。
一个好的线程写法,应该是提交和任务相分离。如果代码中出现这样的语句:new Thread(Runnable).start()
这是一个糟糕的写法,因为这意味着,创建的线程永远无法被人工的终止,当大量创建这样的线程时,这些线程就相当于无政府主义者,不受约束,一旦产生,将会自生自灭。而且这样 的线程不容易修改,假如工程中有一百个上述代码片段,现在任务要变成同步执行(原先的写法肯定是并发执行),如何?这样改动可能要该100处,这对于维护者或者重构者来说简直就是灾难。
好的写法应该是任务的提交和创建相分离(上面是典型的创建和提交混合在一起了)。
比如如下代码:
public class MyThreadSubmitter implements Executor {
@Override
public void execute(Runnable command) {
Thread thread = new Thread(command);
thread.start();
}
}
当想同步执行时,换一个方式就可以了,只需要改动一处,代码如下:
public class MyThreadSubmitter implements Executor {
@Override
public void execute(Runnable command) {
command.run();
}
}
上面阐述了任务的提交和创建相分离,回归老问题:如何终止一个线程?上面已经简要回答了下:即由程序员来维护线程,在程序员写代码的时候,就要考虑到线程终止,通过响应线程中断信号来实现。而不是交由JVM,任凭JVM来销毁,这样是不符合业务逻辑的。
那么如何来编写响应中断式的线程?这个用一个例子来说明。
public class Task implements Runnable {
@Override
public void run() {
try {
boolean isInterrupt = false;
while (!(isInterrupt = Thread.interrupted())) {
//处理业务逻辑
}
if (isInterrupt) {//相应线程中断
}
} catch (Throwable e) {//防止线程泄漏
e.printStackTrace();
} finally{
//释放资源
}
}
} 如何提交呢?
public class TaskSubmiter { private static ExecutorService executor = Executors.newCachedThreadPool(); private List<Future<?>> futures = new ArrayList<Future<?>>(); public void sumbit(Task task){ futures.add(executor.submit(task)); } public void stop(){ for (int i = 0; i < futures.size(); i++) { Future<?> future = futures.get(i); if (!future.isCancelled()) { future.cancel(true); } } futures.clear(); } }
因为TaskSubmiter是任务的提交者,故TaskSubmiter持有线程的上线文信息,发送停止指令,应发送到该类。stop接口提现了线程的停止。以上就是一个通过响应中断来实现线程停止的简单模型。
相关文章推荐
- 关于java中多线程的问题的一点思考(什么情况下需要考虑到线程,以及线程安全的问题?)
- java高级多线程编程(一)--关于线程的停止问题
- java高级多线程编程(一)--关于线程的停止问题
- java高级多线程编程--关于线程的停止问题
- java高级多线程编程(一)--关于线程的停止问题
- java高级多线程编程--关于线程的停止问题
- java高级多线程编程--关于线程的停止问题
- 关于java线程的停止问题(转载至 http://dev.21tx.com 2005年05月03日 Matrix-与Java共舞 )
- java高级多线程编程--关于线程的停止问题
- 关于Java中停止线程执行的方法总结
- java高级多线程编程--关于线程的停止问题
- java高级多线程编程--关于线程的停止问题
- J2SE综合:JAVA语言关于字符串替换的思考
- [Java]关于堆和栈的一些思考
- 关于java数组的深度思考
- 关于线程的讲解?(出自Java原著)
- 关于利用JAVA开发游戏外挂的几点思考
- Java入门:关于Java栈与堆的深入思考
- 关于线程的讲解?(出自Java原著)
- 如果我是国王:关于解决 Java 编程语言线程问题的建议