Java 信号量实现的面向生产者-消费者的线程池
我目前正在从事一项教育任务,其中我必须实现一个仅限信号量的线程安全线程池 我在分配任务期间不得使用:Java 信号量实现的面向生产者-消费者的线程池,java,multithreading,threadpool,semaphore,producer-consumer,Java,Multithreading,Threadpool,Semaphore,Producer Consumer,我目前正在从事一项教育任务,其中我必须实现一个仅限信号量的线程安全线程池 我在分配任务期间不得使用:同步等待通知睡眠或任何线程安全API 首先,我没有过多地使用代码: 实现了一个线程安全队列(没有两个线程可以同时排队\dequeue)(我已经用ConcurrentLinkedQueue测试了这个问题,但问题仍然存在) 设计本身: 共享: 任务信号量=0 可用信号量=0 任务\u队列队列 可用队列队列 工作线程: 阻塞信号量=0 一般信息: 只有管理器(单线程)可以退出任务队列和可用
同步
等待
通知
睡眠
或任何线程安全API
首先,我没有过多地使用代码:
- 实现了一个线程安全队列(没有两个线程可以同时排队\dequeue)(我已经用
测试了这个问题,但问题仍然存在)ConcurrentLinkedQueue
信号量=0任务
信号量=0可用
队列任务\u队列
队列可用队列
信号量=0阻塞
- 只有管理器(单线程)可以退出
和任务队列
可用队列
- 只有App Main(单线程)可以将任务排入队列
tasks\u Queue
- 每个工作线程都可以在
Available\u队列中排队
- 当应用程序第一次启动时,每个工作线程都会启动并立即在
中排队,释放Available\u Queue
信号量并被阻止获取其个人Available
信号量blocked
- 每当App Main将新任务排入队列时,它就会释放
Semaphoretask
- 每当经理希望执行新任务时,必须首先获取
和任务
信号量可用
dequeue\u worker()
返回一个空的worker,即使在已知没有可用的worker线程时放置了一个信号量来保护对队列的访问
我已经通过递归调用dequeue\u worker()
解决了这个问题,如果它绘制了一个空线程,那么这样做会使信号量许可证的获取永远丢失。然而,当我将工人数量限制为1时,工人不会永远被阻止
1) 我最初设计的转折点是什么
2) 为什么我的“解决方案”没有进一步破坏设计
代码片段:
// only gets called by Worker threads: enqueue_worker(this);
private void enqueue_worker(Worker worker) {
available_queue.add(worker);
available.release();
}
// only gets called by App-Main (a single thread)
public void enqueue_task(Query query) {
tasks_queue.add(query);
tasks.release();
}
// only gets called by Manager(a single Thread)
private Worker dequeue_worker() {
Worker worker = null;
try {
available.acquire();
worker = available_queue.poll();
} catch (InterruptedException e) {
// shouldn't happen
} // **** the solution: ****
if (worker==null) worker = dequeue_worker(); // TODO: find out why
return worker;
}
// only gets called by Manager(a single Thread)
private Query dequeue_task() {
Query query = null;
try {
tasks.acquire();
query = tasks_queue.poll();
} catch (InterruptedException e) {
// shouldn't happen
}
return query;
}
// gets called by Manager (a single thread)
private void execute() { // check if task is available and executes it
Worker worker = dequeue_worker(); // available.down()
Query query = dequeue_task(); //task.down()
worker.setData(query);
worker.blocked.release();
}
最后是Worker的Run()
方法:
while (true) { // main infinite loop
enqueue_worker(this);
acquire(); // blocked.acquire();
<C.S>
available.release();
}
while(true){//main无限循环
让工作人员排队(本);
acquire();//已阻止。acquire();
可用。释放();
}
您正在调用available.release()
两次,一次在让工作人员排队
,第二次在主循环中。它的线程安全不阻塞。我的阻塞机制是通过Available
和Tasks
信号量实现的。您的递归迭代也执行相同的操作,但效率非常低。我想了解Available.acquire()调用空对象的.poll()是如何实现的。您调用了Available.release()
两次,一次在enqueue\u worker
中,第二次在大循环中我怎么会错过这个?!非常感谢你!请编辑您的答案,以反映这个捕获,我会选择是作为首选答案。