1

我有一个向站点发出 HTTP 请求的应用程序,ant 然后检索响应,检查它们,如果包含特定关键字,则将 HTTP 请求和响应写入 XML 文件。此应用程序使用蜘蛛来绘制站点的所有 URL,然后发送请求(站点地图中的每个 URL 都被馈送到发送请求的单独线程)。这样我就无法知道所有请求何时发送。最后,我要求将 XML 文件转换为其他格式。因此,为了找出请求何时结束,我使用以下策略:

我将每个请求的时间存储在一个变量中(当一个新请求的发送时间晚于变量中的时间时,该变量会被更新)。另外我启动一个线程来监控这个时间,如果当前时间和变量中的时间相差超过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
    }
}

这种方法正确吗?或者有没有更好的方法可以实现同样的事情。

4

2 回答 2

1

您当前的方法不可靠。您将进入竞争条件 - 如果线程正在更新时间并且另一个线程正在同时读取它。此外,在多个线程中处理请求也很困难。您假设任务在 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 使用线程池执行下载/处理

主要的() {

  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);

}

于 2013-05-20T06:48:42.897 回答
0

一般注意事项:

  1. Java 中的类应该以大写字母开头

  2. 您的线程之间似乎没有同步;访问last_request可能应该是同步的

  3. 使用System.currentTimeMillis()会为您节省一些对象的创建开销

  4. 吞下这样的异常不是一个好习惯

回答:

你的做法是可以接受的。没有太多忙碌的等待,这个想法很简单。哪个好。

我会考虑将等待时间更改为较低的值;数据很少,即使每秒执行一次循环也不会占用太多的处理能力,并且肯定会改善您应用程序的反应时间。

于 2013-05-20T06:48:12.947 回答