Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.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_Concurrency_Queue_Executorservice_Executor - Fatal编程技术网

Java 优雅地实现服务的队列长度指示器

Java 优雅地实现服务的队列长度指示器,java,concurrency,queue,executorservice,executor,Java,Concurrency,Queue,Executorservice,Executor,为什么,java.util.concurrent为什么不为其ExecutorService提供队列长度指示器?最近我发现自己在做这样的事情: ExecutorService queue = Executors.newSingleThreadExecutor(); AtomicInteger queueLength = new AtomicInteger(); ... public void addTaskToQueue(Runnable runnable) { if (queueLen

为什么,
java.util.concurrent
为什么不为其
ExecutorService
提供队列长度指示器?最近我发现自己在做这样的事情:

ExecutorService queue = Executors.newSingleThreadExecutor();
AtomicInteger queueLength = new AtomicInteger();
...

public void addTaskToQueue(Runnable runnable) {
    if (queueLength.get() < MAX_QUEUE_LENGTH) {
        queueLength.incrementAndGet(); // Increment queue when submitting task.
        queue.submit(new Runnable() {
            public void run() {
                runnable.run();
                queueLength.decrementAndGet(); // Decrement queue when task done.
            }
        });
    } else {
        // Trigger error: too long queue
    }
}
ExecutorService queue=Executors.newSingleThreadExecutor();
AtomicInteger queueLength=新的AtomicInteger();
...
public void addTaskToQueue(可运行可运行){
if(queueLength.get()
这很好,但是。。。我认为这确实应该作为
ExecutorService
的一部分来实现。携带一个与实际队列分离的计数器是愚蠢且容易出错的,计数器应该指示该队列的长度(让我想起C数组)。但是,
ExecutorService
s是通过静态工厂方法获得的,因此无法简单地扩展其他优秀的单线程执行器并添加队列计数器。那么我应该怎么做:

  • 重新发明已经在JDK中实现的东西
  • 其他聪明的解决方案

  • 有一种更直接的方法:

    ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newSingleThreadExecutor();
    // add jobs
    // ...
    int size = executor.getQueue().size();
    

    虽然您可以考虑不使用便利性创建执行器的方法,而是直接创建执行器以摆脱CAST,从而确保执行器将始终是一个<代码> TracePoLeExtExotoor <代码>,即使执行<代码>执行器。NexSunLeLeDeXeCutoor 会有一天发生变化。

    ThreadPoolExecutor executor = new ThreadPoolExecutor( 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>() );
    
    ThreadPoolExecutor executor=new ThreadPoolExecutor(1,1,0L,TimeUnit.millides,new LinkedBlockingQueue());
    

    这是直接从JDK 1.6中的
    Executors.newSingleThreadExecutor
    复制的。传递给构造函数的
    LinkedBlockingQueue
    实际上就是您将从
    getQueue

    返回的对象,而您可以直接检查队列大小。处理过长队列的另一种方法是使内部队列有界

    public static
    ExecutorService newFixedThreadPoolWithQueueSize(int nThreads, int queueSize) {
      return new ThreadPoolExecutor(nThreads, nThreads,
                                  5000L, TimeUnit.MILLISECONDS,
                                  new ArrayBlockingQueue<Runnable>(queueSize, true));
    }
    
    公共静态
    ExecutorService newFixedThreadPoolWithQueueSize(int-nThreads,int-queueSize){
    返回新的ThreadPoolExecutor(第n个线程,第n个线程,
    5000L,时间单位为毫秒,
    新的ArrayBlockingQueue(queueSize,true));
    }
    
    当您超过限制时,这将导致RejectedExecutionException(请参阅)

    如果要避免异常,调用线程可能被劫持以执行函数。请参阅以获得解决方案

    工具书类

    Ha!所以您只需要重新实现JDK中非常小的部分(一行)。非常可以接受:-)谢谢。事实上,我自己也会选择这个角色,因为ThreadPoolExecutor是一个公共类,因此在某种程度上也是newSingleThreadExecutor的公共API的一部分。我认为newSingleThreadExecutor创建的对象不再是ThreadPoolExecutor的可能性要小一些,而newSingleThreadExecutor中构造函数调用的参数某天可能会改变,即使用更有效或更精确的实现或其他什么。讽刺的是,在一台机器上我尝试了这一点,我得到了一个
    FinalizableDelegatedExecutorService
    而不是
    ThreadPoolExecutor
    。看看,我不知道如何将
    ExecutorService
    直接强制转换到
    ThreadPoolExecutor
    。而且我总是得到一个
    ClassCastException
    ,就像往常一样。