我正在运行简单的customer_id | Product #1 | Product #2
------------+------------+-----------
1 | DVD | Blu-ray
2 | DVD |
,其运行方法如下
thread
如果我通过public run()
while(!stopFlag){
// print something Line 1
// print something Line 2
// print something Line 3
// print something Line 4
}
viz
ExecutorService
我停止ExecutorService exs = Executors.newFixedThreadPool(5);
exs.execute(new MyThread));
ExecutorService
但是这不会阻止线程,因为标志未设置为false。在another question related to same topic中,我被要求正确处理在调用exs.shutdown()时引起的InterruptedException。 但在这种情况下,我没有做任何可以抛出InterruptedException的动作。
处理此类案件的标准方法是什么?
进一步的问题 Sabir给出的答案说:“如果你的可运行对中断反应不好,除了关闭JVM之外什么都不能阻止它。”。这似乎是我的情况。
但是如何引入InterruptedException的处理;如果我没有调用任何抛出中断异常的方法?
答案 0 :(得分:1)
如果你愿意关闭你的线程,即使该标志仍然是真的,你应该使用 - ExecutorService.shutdownNow()
方法而不是ExecutorService.shutdown()
从Java Docs引用,
shutdown()
启动以前提交的任务的有序关闭 已执行,但不会接受任何新任务。调用没有 如果已经关闭则会产生额外的影
此方法不会等待先前提交的任务完成 执行。使用awaitTermination来做到这一点。
shutdownNow()
尝试停止所有正在执行的任务,停止处理 等待任务,并返回正在等待的任务列表 执行。
此方法不等待主动执行任务终止。 使用awaitTermination来做到这一点。
除了努力尝试停止处理之外,没有任何保证 积极执行任务。例如,典型的实现方式 通过Thread.interrupt取消,因此任何无法响应的任务 中断可能永远不会终止。
对于标准方式,我将引用ExecutorService
接口中的JDK示例,
使用示例
Here is a sketch of a network service in which threads in a thread pool service incoming requests. It uses the preconfigured Executors.newFixedThreadPool factory method: class NetworkService implements Runnable { private final ServerSocket serverSocket; private final ExecutorService pool;
public NetworkService(int port, int poolSize)
throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize); }
public void run() { // run the service
try {
for (;;) {
pool.execute(new Handler(serverSocket.accept()));
}
} catch (IOException ex) {
pool.shutdown();
} } }
class Handler implements Runnable { private final Socket socket; Handler(Socket socket) { this.socket = socket; } public void run() {
// read and service request on socket } }} The following method shuts down an ExecutorService in two phases, first by calling shutdown to reject incoming tasks, and then calling shutdownNow, if necessary, to cancel any lingering tasks: void shutdownAndAwaitTermination(ExecutorService pool) { pool.shutdown(); // Disable new tasks from being submitted try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
} } catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt(); } }}
请注意,即使使用shutdownNow()
也无法保证。
编辑:如果我将您的while(!stopFlag)
更改为while(!Thread.currentThread().isInterrupted())
,那么使用条件循环的线程将使用shutdownNow()
关闭但不会使用shutdown()
关闭被shutdownNow()
打断。我在JDK8和Windows 8.1上。我必须在主线程中进行睡眠,以便服务可以花时间设置服务并启动runnable。线程被启动,进入,然后在调用shutdownNow()
时停止。我没有得到shutdown()
的那种行为,即线程永远不会出现在while循环中。因此,应该通过检查标志或处理异常来使你的runnables负责中断的方法。如果您的runnable对中断没有很好的响应,那么除了关闭JVM之外,不能做任何事情来阻止它。
显示了一个好的方法here
答案 1 :(得分:0)
从您的问题中我很好地假设您正在尝试优雅地关闭该过程。为此,您需要注册shutdownHook来实现它。以下是实现它的示例代码。
package com.example;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadManager {
public static void main(String[] args) {
MyThread myThread = new MyThread();
Runtime.getRuntime().addShutdownHook(new Thread(){
MyThread myThread = null;
@Override
public void run(){
System.out.println("Shutting down....");
this.myThread.stopProcess();
}
public Thread setMyThread(MyThread myThread){
this.myThread=myThread;
return this;
}
}.setMyThread(myThread));
ExecutorService exs = Executors.newFixedThreadPool(5);
myThread.setName("User");
exs.execute(myThread);
exs.shutdownNow();
}
}
在MyThread.java中将如下所示: -
package com.example;
public class MyThread extends Thread{
private boolean stopFlag;
@Override
public void run(){
while(!stopFlag){
System.out.println(this.getName());
}
}
public void stopProcess(){
this.stopFlag=true;
}
}
现在,如果您创建此代码的jar文件并在Linux服务器中运行以查看它是如何工作的,那么请执行以下附加步骤
Step 1> nohup java -jar MyThread.jar &
按ctrl + c存在 现在使用以下命令找到pid
Step 2> ps -ef| grep MyThread.jar
获得pid后执行以下命令以正常停止
Step 3>kill -TERM <Your PID>
当您检查nohub.out文件时,输出将类似于
User
User
.
.
.
User
Shutting down....
User
.
.
请记住,如果您尝试使用kill -9关闭,则永远不会看到Shutting down....
消息。
@Sabir已经讨论了shutdown
和shutdownNow
之间的区别。但是,我绝不会建议您在线程运行时使用interrupt
调用。它可能会导致实时环境中的内存泄漏。
Upadte 1: -
public static void main(String[] args) {
MyThread myThreads[] = new MyThread[5];
ExecutorService exs = Executors.newFixedThreadPool(5);
for(int i=0;i<5;++i){
MyThread myThread = new MyThread();
myThread.setName("User "+i);
exs.execute(myThread);
myThreads[i] = myThread;
}
Runtime.getRuntime().addShutdownHook(new Thread(){
MyThread myThreads[] = null;
@Override
public void run(){
System.out.println("Shutting down....");
for(MyThread myThread:myThreads){
myThread.stopProcess();
}
}
public Thread setMyThread(MyThread[] myThreads){
this.myThreads=myThreads;
return this;
}
}.setMyThread(myThreads));
exs.shutdownNow();
}