0

当我尝试从头开始为 http 请求实现队列时遇到问题。抱歉,这对某人来说可能是一个非常幼稚的并发问题。

基本上我希望我的应用程序在任何时候都只执行一个请求。额外的请求进入队列并稍后执行。

我知道其他高级的东西,例如 FutureTask 和 Execution pool,但我想要答案,因为我很好奇如何解决基本的并发问题。以下是我的班级维护 requestQueue

private Queue<HttpRequest> requestQueue;
private AsyncTask myAsyncTask=null;

public boolean send(HttpRequest hr){
   //if there isn't existing task, start a new one, otherwise just enqueue the request
   //COMMENT 1.
   if(myAsyncTask==null){
     requestQueue.offer(hr);
     myAsyncTask= new RequestTask();
     myAsyncTask.execute(null);
     return true;
   }
   else{
     //enqueue
     //COMMENT 2
     requestQueue.offer(hr);
   }

}

//nested class
RequestTask extends AsyncTask<boolean,void,void>{
      protected HttpResponse doInBackground(void... v){
           //send all request in the queue
           while(requestQueue.peek != null){
              HttpResquest r= requestQueue.poll
              //... leave out code about executing the request
           }
           return true;
      }

      protected void doPostExecute(boolean success){


           //COMMENT 3: if scheduler stop here just before myAsyncTask is set to null
           myAsyncTask=null;

      }
}

问题是,如果线程调度程序在 COMMENT 3 点停止后台线程(就在 myAsyncTask 设置为 null 之前)。

      //COMMENT 3: if scheduler stop here just before myAsyncTask is set to null
       myAsyncTask=null;

当时,其他线程碰巧到 COMMENT 1 点并进入 if ... else ... 块。因为 myAsyncTask 没有设置为 null,所以任务在 else 块中排队(注释 2),但不会创建新的 asyncTask,这意味着队列会卡住!

   //COMMENT 1.
   if(myAsyncTask==null){
     requestQueue.offer(hr);
     myAsyncTask= new RequestTask;
     myAsyncTask.execute(null);
     return true;
   }
   else{
     //enqueue
     //COMMENT 2
     requestQueue.offer(hr);
   }

我希望很清楚。队列有可能停止处理。我很想知道如何避免这种情况。先感谢您

4

1 回答 1

0

我通常实现这样的方式是创建一个扩展线程的类。这将包含一个队列对象(使用您喜欢的任何一个)并具有添加作业的方法。我会使用同步来保证所有线程的安全。可以使用通知和等待来避免轮询。

这是一个可能有帮助的例子......

    import java.util.*;

    public class JobProcessor extends Thread
    {
       private Queue queue = new LinkedList();

       public void addJob(Object job)
       {
           synchronized(queue)
           {
              queue.add(job);
              queue.notify(); // lests the thread know that an item is ready
           }
       }


       @Overide
       public void run()
       {
          while (true)
          {
              Object job = null;

              synchronized(queue) // ensures thread safety
              {
                 // waits until something is added to the queue.
                 try
                   while (queue.isEmpty()) queue.wait();
                 catch (InterruptedException e)
                   ; // the wait method can throw an exception you have to catch.
                 // but can ignore if you like.

                 job = queue.poll();
              }
              // at this point you have the job object and can process it!
              // with minimal time waiting on other threads.
              // be sure to check that job isn't null anyway!
              // in case you got an InterruptedException.

              ... processing code ...

              // job done loop back and wait for another job in the queue.
          }
       }
    }

您几乎只需要像这样实例化一个类并启动线程,然后开始插入对象来处理作业。当队列为空时,等待会导致该线程休眠(并且还会暂时释放同步锁),addJob 方法中的 notify 会在需要时将其唤醒。同步是一种确保只有一个线程可以访问队列的方法。如果您不确定它是如何工作的,请在 java SDK 参考中查找。

您的代码中没有任何线程安全代码(同步内容),这就是您的问题所在。它可能有点过于复杂,也无法帮助您调试它。但最重要的是您需要添加同步块,但请确保它们尽可能短。

于 2013-01-22T02:04:35.683 回答