我有一个应用程序向站点发出HTTP请求,然后ant检索响应,检查它们,如果包含特定关键字,则将HTTP请求和响应写入XML文件。此应用程序使用蜘蛛来映射站点的所有URL,然后发送请求(站点地图中的每个URL都被送到发送请求的单独线程)。这样我就无法知道所有请求何时发送。在我要求的最后,我想将XML文件转换为其他格式。因此,为了找出请求何时结束,我使用以下策略:
我将每个请求的时间存储在varible中(当在比变量中的时间晚的时间发送新请求时,varible被更新)。此外,我开始一个线程来监控这个时间,如果当前时间和变量中的时间差异超过1分钟,我知道发送请求已经停止。我为此目的使用以下代码:
class monitorReq implements Runnable{
Thread t;
monitorReq(){
t=new Thread(this);
t.start();
}
public void run(){
while((new Date().getTime()-last_request.getTime()<60000)){
try{
Thread.sleep(30000);//Sleep for 30 secs before checking again
}
catch(IOException e){
e.printStackTrace();
}
}
System.out.println("Last request happened 1 min ago at : "+last_request.toString());
//call method for conversion of file
}
}
这种做法是否正确?或者有更好的方法可以实现同样的事情。
答案 0 :(得分:1)
您目前的做法并不可靠。你将进入竞争条件 - 如果线程正在更新时间&amp;另一个线程正在同时读取它。此外,在多个线程中处理请求也很困难。你假设任务在60秒内完成..
以下是更好的方法。
如果你知道你要提前做出的请求数量,你可以使用CountDownLatch
main() {
int noOfRequests = ..;
final CountDownLatch doneSignal = new CountDownLatch(noOfRequests);
// spawn threads or use an executor service to perform the downloads
for(int i = 0;i<noOfRequests;i++) {
new Thread(new Runnable() {
public void run() {
// perform the download
doneSignal.countDown();
}
}).start();
}
doneSignal.await(); // This will block till all threads are done.
}
如果您事先不知道请求的数量,那么您可以使用executorService来使用线程池执行下载/处理
main(){
ExecutorService executor = Executors.newCachedThreadPool();
while(moreRequests) {
executor.execute(new Runnable() {
public void run() {
// perform processing
}
});
}
// finished submitting all requests for processing. Wait for completion
executor.shutDown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.Seconds);
}
答案 1 :(得分:0)
一般说明:
类应该从Capital Letters
您的线程之间似乎没有同步;可能应该同步对last_request
的访问
使用System.currentTimeMillis()
可以节省一些对象的创建开销
吞下像这样的例外不是一个好习惯
<强>答案:强>
你这样做是可以接受的。没有太多忙碌的等待,这个想法就像它得到的一样简单。这很好。
我会考虑将等待时间更改为较低的值;如此少的数据,即使每秒执行此循环也不会占用太多处理能力,并且肯定会从您的应用程序中改善执行时间。