gpt4 book ai didi

android - 使用 SynchronousQueue 的指南

转载 作者:行者123 更新时间:2023-11-29 02:08:26 25 4
gpt4 key购买 nike

我需要执行一系列 http 请求,每个请求都可能依赖于先前的 http 响应。我已经能够使用各种 AsyncTask“树”来实现这一点,但是随着决策树的增长,AsyncTask 技术变得更加笨拙。

我认为以某种方式使用 SynchronousQueue(或其他类型的队列)是最好的方法,但我似乎找不到任何关于如何将队列用于 http 请求之类的好的指导或教程。

任何人都可以提供有关使用 SynchronousQueue 的任何指导或指向任何好的教程或建议最好的队列类型吗?

最佳答案

使用 java.util.concurrent.SingleThreadExecutor并制作一个Runnable在每个 HTTP 操作和结果处理程序之外。您可以在确定是否需要继续进行时向其提交后续任务。

例如,HTTP“任务”将运行并在成功时提交结果“任务”,或在失败时提交错误“任务”。 Result 任务在完成处理后将依次提交另一个 HTTP 任务。使用 SingleThreadExecutor确保一次只运行一个任务。

你可以使用 ThreadPoolExecutor如果您可以同时处理飞行中的多个操作。

把所有这些都拿走,然后把它包装在一个 AsyncTask 中管理顶级“启动”并等待一切完成。拥有 ConditionVariable 可能会很有用或者同步“结束”信号的东西(使用完成“任务”),这样你就可以安全地拆除 Executor .

A SynchronousQueue在这里对您没有任何帮助,因为它让您进行所有胎面管理。如果您使用 Executor所有这些都已处理,您只需要处理 Runnable s 和 Future秒。这可能就是您找不到任何教程的原因。无论如何,Executor所有这些都使用下面的队列实现之一!

根据要求,这里是一些框架 Java 代码。不受支持,未经测试。这应该让你开始。如果您不喜欢 ConditionVariable,您可以使用不同的同步对象.

这是一种通用技术,并非特定于 Android,您可以在其他情况下随意使用它。

这用作状态机,带有 HttpTask等人形成状态,并通过将下一个状态提交给 ExecutorService 来对转换进行硬编码。 .甚至还有一个“大爆炸在最后,所以每个人都知道什么时候鼓掌”的形式 ConditionVariable .

有些人可能会考虑 DoneTaskFailedTask矫枉过正,但它使 Next State 机制保持一致,并让 Future<? extends ResultTask>用作结果的类型安全容器,当然可以防止您错误分配给它。

abstract class BasicTask {
final ExecutorService es;
final ConditionVariable cv;
public BasicTask(ExecutorService es, ConditionVariable cv) {
this.es = es;
this.cv = cv;
}
}
abstract class HttpTask extends BasicTask {
// source omitted.
// you should make a class to prepare e.g. Apache HTTP resources for specific tasks (see below).
}
abstract class ResultTask implements Runnable {
final ConditionVariable cv;
public ResultTask(ConditionVariable cv) {
this.cv = cv;
}
public void run() {
cv.open();
}
}
final class FailedTask extends ResultTask {
final Exception ex;
public FailedTask(ConditionVariable cv, Exception ex) {
super(cv);
this.ex = ex;
}
public Exception getError() { return ex; }
}
final class DoneTask<T> extends ResultTask {
final T results;
public DoneTask(ConditionVariable cv, T results) {
super(cv);
this.results = results;
}
public T getResults() { return results; }
}

class HttpSequence extends AsyncTask<Void,Void,Object> {
// this will capture the ending task
Future<? extends ResultTask> result;
// this is an inner class, in order to set Result. Refactor so these are small.
// if you don't like inner classes, you still need to arrange for capturing the "answer"
final class SomeHttpTask extends HttpTask implements Runnable {
public void run() {
try {
final SomeType thisStep = doTheStuff(lastStep);
if(thisStep.isDone()) {
// we are done here
result = es.submit(new DoneTask<SomeType>(cv, thisStep));
}
else if(thisStep.isFailed()) {
// not done: we can't proceed because of something in the response
throw thisStep.getError();
}
else {
// not done, everything is ok for next step
es.submit(new NextHttpTask(es, cv, thisStep));
}
}
catch(Exception ex) {
result = es.submit(new FailedTask(cv, ex));
}
}
}
final class TheFirstTask extends HttpTask implements Runnable {
// source omitted. just emphasizing you need one of these for each "step".
// if you don't need to set Result, this could be a static inner class.
}

@Override
public Object doInBackground(Void...) {
final ExecutorService es = Executors.newSingleThreadExecutor();
final ConditionVariable cv = new ConditionVariable(false);
try {
es.submit(new TheFirstTask(es, cv));
// you can choose not to timeout at this level and simply block until something happens...
final boolean done = cv.block(timeout);
if(!done) {
// you will need to account for unfinished threads, see finally section!
return new IllegalStateException("timed out waiting on completion!");
}
if(result != null) {
final ResultTask done = result.get();
if(done instanceof DoneTask) {
// pass SomeType to onPostExecute()
return ((DoneTask<SomeTYpe>)done).getResults();
}
else if(done instanceof FailedTask) {
// pass Exception to onPostExecute()
return ((FailedTask)done).getError();
}
else {
// something bad happened, pass it to onPostExecute()
return new IllegalStateException("something unexpected signalled CV!");
}
}
else {
// something bad happened, pass it to onPostExecute()
return new IllegalStateException("something signalled CV without setting result!");
}
}
catch(Exception ex) {
// something outside workflow failed, pass it to onPostExecute()
return ex;
}
finally {
// naive shutdown (doesn't interrupt running tasks): read JavaDoc on ExecutorService for details
es.shutdown();
}
}
@Override
public void onPostExecute(Object result) {
if(result instanceof SomeType) {
// success UI
}
else if(result instanceof Exception) {
// error UI
}
}
}

关于android - 使用 SynchronousQueue 的指南,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8693359/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com