当我尝试从头开始为 http 请求实现队列时,我遇到了问题。抱歉,这对某些人来说可能是一个非常幼稚的并发问题。
基本上,我希望我的应用程序在任何时候只执行一个请求。额外的请求进入队列并在稍后执行。
我知道其他高级的东西,如FutureTask和执行池,但我想要答案,因为我对如何解决基本的并发问题感到好奇。以下是我的类维护请求队列
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 ...还。。。块。因为 myAsyncTask 没有设置为 null,所以任务会在 else 块(COMMENT 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);
}
我希望这是清楚的。队列可能会停止处理。我很想知道如何避免这种情况。提前谢谢你
我通常实现这样的东西的方式是创建一个扩展线程的类。这将包含一个队列对象(使用您喜欢的任何对象),并且具有添加作业的方法。我会使用同步来确保所有线程安全。通知和等待可用于避免轮询。
这里有一个可能会有所帮助的示例...
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 方法中的通知会在需要时将其唤醒。同步是一种确保只有一个线程可以访问队列的方法。如果您不确定它是如何工作的,请在 java SDK 参考中查找它。
您的代码中没有任何线程安全代码(同步内容),这就是您的问题所在。它可能有点过于复杂,也无助于您调试它。但最主要的是您需要添加同步块,但请确保它们尽可能短。