我在glassfish下创建了一个新的线程池和一个新的关联监听器。线程池的最大容量为100个线程。我有一个每晚运行的预定作业,它应该从远程客户端触发HTTP GET请求。请注意,预定作业是不 HTTP客户端。但是它会触发远程HTTP客户端发出HTTP GET请求。请求的数量可以超过100.即使请求数超过100,预定作业也应以不间断的方式运行。以下是伪代码
class ScheduledJob{
public executeJob(){
{
for(i=0; i<=numberOfTasks; i++)
{
connectToTheClientsAndAskThemToFireHTTPGetRequests();
}
}
}
我想设计解决方案的方法是使 executeJob 方法以非阻塞方式执行。这意味着最初会触发100个请求,其余请求将被缓存。收到200 OK后,我会限制其余的请求。请注意,HTTP请求可能需要几秒钟,因为响应HTTP GET是一个20MB的二进制文件。这里的问题是有没有开箱即用的解决方案(数据结构)来执行我的缓存和触发业务逻辑,或者任何人都可以提出更好的解决方案。
答案 0 :(得分:1)
一个选项是创建一个Runnable
,它采用GetTasks
的并发队列(或任何你想要命名的HTTP GET请求数据的包装器)。 executeJob()
使用所有GetTasks
填充队列,构造一个包含100个线程的线程池,并提交共享同一并发队列的100 Runnables
。 Runnables
将轮询队列,直到它为空,此时它们终止。
public class GetTask {}
public class GetTaskExecutor implements Runnable {
private final ConcurrentLinkedQueue<GetTask> queue;
public GetTaskExecutor(ConcurrentLinkedQueue<GetTask> queue) {
this.queue = queue;
}
public void run() {
GetTask task = null;
while((task = queue.poll()) != null) {
// do work
}
}
}
class ScheduledJob{
public boolean executeJob(){
ExecutorService service = Executors.newFixedThreadPool(100);
ConcurrentLinkedQueue<GetTask> queue = new ConcurrentLinkedQueue<>();
for(i=0; i<=numberOfTasks; i++) {
queue.offer(new GetTask());
}
for(int i = 0; i < 100; i++) {
service.execute(new GetTaskExecutor(queue));
}
return service.awaitTermination(4, TimeUnit.HOURS);
}
}
另一种方法是每GetTaskExecutor
创建一个GetTask
并将其全部提交给ExecutorService
- 您正在使用固定的线程池,因此一次最多可执行100个任务
public class GetTaskExecutor implements Runnable {
private final GetTask task;
public GetTaskExecutor(GetTask task) {
this.task = task;
}
public void run() {
// do work on single task
}
}
class ScheduledJob{
public boolean executeJob(){
ExecutorService service = Executors.newFixedThreadPool(100);
for(i=0; i<=numberOfTasks; i++) {
service.execute(new GetTaskExecutor(new GetTask());
}
return service.awaitTermination(4, TimeUnit.HOURS);
}
}