【发布时间】:2015-03-16 14:50:42
【问题描述】:
有一个线程连接到服务器(HTTP)并在循环中等待响应或响应超时(服务器直到有数据返回时才响应)。如果响应返回一个线程处理它。
在服务停止时,需要停止/中断所有线程,但线程必须完成响应处理(如果线程正在处理而不仅仅是等待响应)。
这是代码示例
public class WaitingResponseThread extends Thread {
static final int TIMEOUT = 4 * 1000;
static final int PROCESSING_DURATION = 2000;
private volatile boolean stopped = false;
private volatile boolean processing = false;
public void run() {
System.out.println("starting child thread");
while(!stopped) {
try {
// here a thread is awaiting server response (in real life response timeout is 400 sec)
// probably it is safe to interrupt the thread now
// emulating this with Thread.sleep()
System.out.println("awaiting response");
Thread.sleep(TIMEOUT);
processing = true;
// there is some job on response and we must allow it to finish the job
// again emulating delay with Thread.sleep()
Thread.sleep(PROCESSING_DURATION);
processing = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("ending child thread");
}
public void setStopped(boolean stopped) {
this.stopped = stopped;
}
public boolean isProcessing() {
return processing;
}
public static void main(String[] args) {
WaitingResponseThread t = new WaitingResponseThread();
// starting thread, it sends a request and waits for a response
t.start();
try {
Thread.sleep(1);
// let's allow the thread to finish normally in case it is processing response
t.setStopped(true);
System.out.println("awaiting child thread to get response");
Thread.sleep(TIMEOUT + 1);
// let's allow the thread to finish processing
while(t.isProcessing()) {
System.out.println("processing");
Thread.sleep(500);
}
// we can't wait for 400sec until the next loop check
// so as the thread is sleeping we just interrupting it
if(t.isAlive()) {
System.out.println("killing");
t.interrupt();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ending main thread");
}
}
这种“中断”方法好吗?是否有另一种方法可以不等待超时并且不丢失正在处理的数据?
【问题讨论】:
-
另一种方法是使用 Executors docs.oracle.com/javase/8/docs/api/java/util/concurrent/… 然后您可以调用
yourPool.shutdown()和yourPool.awaitTermination(time, unit)但您仍然需要正确处理每个线程中的中断,据我所知没有铸铁方式来确保螺纹始终正确完成。而不是重新发明轮子。 -
如果您仍想完成当前 HTTP 请求的处理,
interrupt方法不是一个好的选择。原因是调用interrupt会导致线程上IO操作的InterruptedIOException被中断,终止IO尝试(并且HTTP请求涉及IO) -
@gumkins 但你只开始一个线程!?你说的“线程列表”在哪里?
-
@isnot2bad,这是一个简化的例子。实际上,我并没有试图将您的注意力集中在多个线程之间的资源共享上。我只需要安全地停止线程。但是您可以想象 ArrayList
及其在 main() 方法中对 t.start()、t.setStopped(true)、t.isProcessing() 和 t.interrupt() 的迭代。为了正义,我修改了主题和描述,但现在恐怕有人会问我为什么需要 1 个线程:-)
标签: java multithreading