Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/215.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中如何确保同时只有一个请求_Java_Android_Kotlin - Fatal编程技术网

在Java中如何确保同时只有一个请求

在Java中如何确保同时只有一个请求,java,android,kotlin,Java,Android,Kotlin,我想实现一个调用,如: public Response getContent() throws MyException 此方法在内部调用web服务,但我只希望同时向web服务发出一个请求。也就是说:当第一个请求出现时,它将转到web服务。如果同时另一个请求到达,它将等待第一个请求的结果。在第一个请求返回(或抛出异常)后,所有挂起的请求也返回(或抛出异常)。从这一点上讲,如果出现另一个请求,它将以相同的条件再次转到web服务(同一时间只有一个web服务调用) 在Java/Android中实现这一

我想实现一个调用,如:

public Response getContent() throws MyException
此方法在内部调用web服务,但我只希望同时向web服务发出一个请求。也就是说:当第一个请求出现时,它将转到web服务。如果同时另一个请求到达,它将等待第一个请求的结果。在第一个请求返回(或抛出异常)后,所有挂起的请求也返回(或抛出异常)。从这一点上讲,如果出现另一个请求,它将以相同的条件再次转到web服务(同一时间只有一个web服务调用)

在Java/Android中实现这一点的最佳方法是什么


谢谢

我建议开始学习阻塞队列的工作原理:

之后,您可以开始研究解决方案,如何一次呼叫一个电话。一种解决方案是使用信号量:

(来自上面的链接)适用于您案例的片段:
编辑

 public class CustomBlockingQueue {
  private List<Object> queue = new LinkedList<Object>();
  private int limit;
  private Semaphore mutex; // for the critical section
  public CustomBlockingQueue() {
    this.mutex = new Semaphore(1);
  }
  //enqueue can be process task, etc.
  private void enqueue(Object o) throws InterruptedException {
    mutex.acquire(); // critical section starts
    queue.add(o); //or custom operation
    mutex.release(); // critical section ends
  }

  //as pointed out in the comments this is more queue related
  private Object dequeue() throws InterruptedException {
    mutex.acquire(); // critical section starts
    Object o = queue.remove(0);//or custom operation
    mutex.release(); // critical section ends
    return o;
  }
}
公共类CustomBlockingQueue{
私有列表队列=新建LinkedList();
私有整数限制;
专用信号量互斥;//用于关键部分
公共CustomBlockingQueue(){
this.mutex=新信号量(1);
}
//排队可以是进程任务等。
私有void排队(对象o)抛出InterruptedException{
mutex.acquire();//临界段开始
queue.add(o);//或自定义操作
mutex.release();//临界段结束
}
//正如评论中指出的,这与队列更相关
private Object dequeue()引发InterruptedException{
mutex.acquire();//临界段开始
对象o=队列。删除(0);//或自定义操作
mutex.release();//临界段结束
返回o;
}
}

我建议开始学习阻塞队列的工作原理:

之后,您可以开始研究解决方案,如何一次呼叫一个电话。一种解决方案是使用信号量:

(来自上面的链接)适用于您案例的片段:
编辑

 public class CustomBlockingQueue {
  private List<Object> queue = new LinkedList<Object>();
  private int limit;
  private Semaphore mutex; // for the critical section
  public CustomBlockingQueue() {
    this.mutex = new Semaphore(1);
  }
  //enqueue can be process task, etc.
  private void enqueue(Object o) throws InterruptedException {
    mutex.acquire(); // critical section starts
    queue.add(o); //or custom operation
    mutex.release(); // critical section ends
  }

  //as pointed out in the comments this is more queue related
  private Object dequeue() throws InterruptedException {
    mutex.acquire(); // critical section starts
    Object o = queue.remove(0);//or custom operation
    mutex.release(); // critical section ends
    return o;
  }
}
公共类CustomBlockingQueue{
私有列表队列=新建LinkedList();
私有整数限制;
专用信号量互斥;//用于关键部分
公共CustomBlockingQueue(){
this.mutex=新信号量(1);
}
//排队可以是进程任务等。
私有void排队(对象o)抛出InterruptedException{
mutex.acquire();//临界段开始
queue.add(o);//或自定义操作
mutex.release();//临界段结束
}
//正如评论中指出的,这与队列更相关
private Object dequeue()引发InterruptedException{
mutex.acquire();//临界段开始
对象o=队列。删除(0);//或自定义操作
mutex.release();//临界段结束
返回o;
}
}

这里有一个解决方案,它具有一个
可完成的未来
,总是阻止等待新结果。如果调用
get()
,并且存在现有结果,则会触发新的获取并阻塞。如果提取已经在进行中,它将加入等待该结果的其他线程

import java.util.concurrent.CompletableFuture
import java.util.concurrent.atomic.AtomicReference

class OneAtATime<out T> {
    private val pending = AtomicReference(CompletableFuture<T>())
    init {
        startFetching(pending.get())
    }

    fun get(): T {
        val current = pending.get()
        if (!current.isDone) {
            return current.get()
        }
        val next = CompletableFuture<T>()
        return if (pending.compareAndSet(current, next)) {
            startFetching(next)
            next.get()
        } else {
            pending.get().get()
        }
    }

    private fun startFetching(future: CompletableFuture<T>) {
        TODO("Implementation must call future.complete(newContent)")
    }
}
import java.util.concurrent.CompletableFuture
导入java.util.concurrent.AtomicReference
一次一类{
private val pending=AtomicReference(CompletableFuture())
初始化{
startFetching(挂起的.get())
}
fun get():T{
val current=pending.get()
如果(!current.isDone){
返回当前值。get()
}
val next=CompletableFuture()
返回if(挂起。比较数据集(当前,下一个)){
开始蚀刻(下一个)
下一步
}否则{
挂起的.get().get()
}
}
私人娱乐开始版画(未来:可完成的未来){
TODO(“实现必须调用future.complete(newContent)”)
}
}

这里有一个解决方案,它具有一个
可完成的未来
,总是阻止等待新结果。如果调用
get()
,并且存在现有结果,则会触发新的获取并阻塞。如果提取已经在进行中,它将加入等待该结果的其他线程

import java.util.concurrent.CompletableFuture
import java.util.concurrent.atomic.AtomicReference

class OneAtATime<out T> {
    private val pending = AtomicReference(CompletableFuture<T>())
    init {
        startFetching(pending.get())
    }

    fun get(): T {
        val current = pending.get()
        if (!current.isDone) {
            return current.get()
        }
        val next = CompletableFuture<T>()
        return if (pending.compareAndSet(current, next)) {
            startFetching(next)
            next.get()
        } else {
            pending.get().get()
        }
    }

    private fun startFetching(future: CompletableFuture<T>) {
        TODO("Implementation must call future.complete(newContent)")
    }
}
import java.util.concurrent.CompletableFuture
导入java.util.concurrent.AtomicReference
一次一类{
private val pending=AtomicReference(CompletableFuture())
初始化{
startFetching(挂起的.get())
}
fun get():T{
val current=pending.get()
如果(!current.isDone){
返回当前值。get()
}
val next=CompletableFuture()
返回if(挂起。比较数据集(当前,下一个)){
开始蚀刻(下一个)
下一步
}否则{
挂起的.get().get()
}
}
私人娱乐开始版画(未来:可完成的未来){
TODO(“实现必须调用future.complete(newContent)”)
}
}

Producer/consumer,也可以是一个。您还可以避免延迟,向每个请求者提供缓存的值,同时继续在后台获取新值。但是如果你坚持阻止,你可以使用
CompletableFuture
。使用同步怎么样?像“最好的X是什么”这样的问题非常主观,并且会吸引基于意见的答案。我们不想要这些,请不要问这样的问题,它们不是“最好的”。只有“出于这个原因才有好处”。任何可行的方法都已经足够好了,但是您需要从一组可能的解决方案中选择更多的标准。生产者/消费者也可以是一个。您还可以避免延迟并向每个请求者交付缓存的值,同时在后台继续获取新的值。但是如果你坚持阻止,你可以使用
CompletableFuture
。使用同步怎么样?像“最好的X是什么”这样的问题非常主观,并且会吸引基于意见的答案。我们不想要这些,请不要问这样的问题,它们不是“最好的”。只有“出于这个原因才有好处”。有什么办法吗