【问题标题】:Check if a threadpool have tasks that are waiting for execution?检查线程池是否有等待执行的任务?
【发布时间】:2016-12-15 14:21:55
【问题描述】:

所以这是我试图提出解决方案的场景:

您有一个有 2000 个免费停车位的停车场。它有4个入口。车位满时,每个入口只能停50辆车。

我最终做的是创建一个有 2000 个线程的线程池,然后是 4 个线程代表入口。他们以随机的时间间隔创建汽车Tasks(他们基本上只是调用Thread.sleep())并将它们提交到线程池。

当线程池忙于执行 2000 个任务时,问题就出现了,新提交的任务被放入队列等待执行。我该如何处理在入口处等待?我似乎找不到检查线程池是否“满”或类似的方法。或者也许我的方法完全错误。

【问题讨论】:

  • 在这种情况下你必须使用线程吗?如果不看看队列。 docs.oracle.com/javase/8/docs/api/java/util/Queue.html
  • 是的,线程和线程池都是必需的。在我看来,即使我在入口处使用了队列,它们仍然会提交给执行器并构建另一个队列。
  • 有一个 ThreadPoolExecutor 构造函数,它接受一个 BlockingQueue 和一个 RejectedExecutionHandler。这看起来很有希望解决这个不错的挑战。我认为你必须做一些额外的编码来表示 4 个入口。 docs.oracle.com/javase/7/docs/api/java/util/concurrent/…
  • 我一定会去看看的!但我似乎已经使用信号量和回调解决了它。每个入口线程都有一个带有 50 个键的信号量。当它完成汽车任务时,它需要一把钥匙。 cartask 然后有一个回调,它在它睡着后被调用。回调只返回一个键给信号量。这似乎工作正常。 :)

标签: java multithreading threadpool


【解决方案1】:

现在我该如何处理在入口处等待的问题?我似乎找不到检查线程池是否“满”或类似情况的方法。

嗯。使用 Java 并发类有很多方法可以做到这一点。一种方法是让BlockingQueue 具有有限的 2000 大小,代表停车场插槽。然后有 4 个单线程 executor-service 线程池,每个线程池都有一个 50 个队列,代表 4 个入口。一旦第 51 辆车试图在入口排队,RejectedExecutionException 就会被抛出。

类似:

final int NUM_SPACES_IN_LOT = 2000;
final int ENTRANCE_QUEUE_SIZE = 50;
final BlockingQueue<Car> parkingLot = new LinkedBlockingQueue<>(NUM_SPACES_IN_LOT);
...
ExecutorService entrance1 = new ThreadPoolExecutor(1, 1,
    0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(ENTRANCE_QUEUE_SIZE));
ExecutorService entrance1 = new ThreadPoolExecutor(1, 1,
    0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(ENTRANCE_QUEUE_SIZE));
ExecutorService entrance1 = new ThreadPoolExecutor(1, 1,
    0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(ENTRANCE_QUEUE_SIZE));
ExecutorService entrance1 = new ThreadPoolExecutor(1, 1,
    0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(ENTRANCE_QUEUE_SIZE));
...
private class ParkCar implements Runnable {
    private final Car car;
    public ParkCar(Car car) {
        this.car = car;
    }
    public run() {
        parkingLot.put(car);
    }
}
...
Car car = new Car();
try {
   entrance1.submit(new ParkCar(car));
} catch (RejectedExecutionException jee) {
   // entrance is full
}
...
// remove a car from the lot, warning this is O(N)
parkingLot.remove(car);

您需要每个入口队列和每个入口线程来执行并发停放。如果您不希望它抛出异常,您可以调用entranceX.setRejectedExecutionHandler(...) 来设置一个入口已满的处理程序。

我不喜欢这个实现的一点是 parkingLot.remove(...)O(N) 但如果不自己编写它就没有阻塞集。

【讨论】:

    猜你喜欢
    • 2019-10-08
    • 2015-07-13
    • 2014-03-18
    • 2011-06-02
    • 2019-09-18
    • 2017-05-20
    • 2020-02-15
    • 1970-01-01
    • 2019-10-24
    相关资源
    最近更新 更多