我一直很好奇Quasar及其轻质纤维作为Threads的替代品。在咨询了他们的API docs后,我无法弄清楚如何将典型的ThreadPoolExecutor转换为光纤池。
int maxThreadPoolSize = 10;
ThreadPoolExecutor executor = new ThreadPoolExecutor(
maxThreadPoolSize,
maxThreadPoolSize,
10, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(maxThreadPoolSize),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
for (int i = 0; i < 100; i++) {
executor.execute(new Runnable() {
@Override
public void run() {
// run some code
}
});
}
上面的代码创建了一个包含10个线程的池,一个可以容纳10个元素的池前面的队列和一个拒绝策略(当队列已满时)让主线程执行Runnable任务本身。当for循环创建100个runnables时,它们将在池中一次执行10个,排队10个,主线程获取Runnable本身直到其他完成,之后主线程返回将Runnables添加到执行程序。 / p>
Quasar的纤维怎么做?是否意味着首先使用它?
编辑:我原来的问题措辞不当。本质上,我试图找到一种机制来限制可同时运行的光纤数量。例如,如果已经运行了200个光纤,则不要启动更多光纤。如果最大光纤数正在运行,请等到一个光纤完成后才启动新光纤。答案 0 :(得分:0)
光纤非常便宜,因此您根本不需要池化(及其异步作业调度模型):只需启动光纤,并在每次需要新的顺序过程时运行常规顺序代码与他人同时运作。
答案 1 :(得分:0)
每个由FiberScheduler调度的光纤,当您创建不带调度程序的Fiber时,都会创建一个FiberForkJoinScheduler并将其分配给该光纤。
简而言之,如果要管理线程池中的光纤,请使用FiberExecutorScheduler:
Quasar's document about scheduling fibers
您的代码可能是这样
int maxThreadPoolSize = 10;
ThreadPoolExecutor executor = new ThreadPoolExecutor(
maxThreadPoolSize,
maxThreadPoolSize,
10, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(maxThreadPoolSize),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
FiberExecutorScheduler scheduler = new FiberExecutorScheduler("FibersInAPool", executor);
for (int i = 0; i < 100; i++) {
Fiber fiber = new Fiber<Void>(scheduler
, new SuspendableCallable<Void>() {
@Override
public Void run() throws SuspendExecution, InterruptedException {
// run some code
return null;
}
});
fiber.start();
}
答案 2 :(得分:-1)
java.util.concurrent.Semaphore最终在我的特定设置中运行良好。
我的解决方案的一般要点:
奖励:标准Java的信号量是固定的,许可证数量无法动态调整。为了使其变得动态,这个链接派上用场:http://blog.teamlazerbeez.com/2009/04/20/javas-semaphore-resizing/
答案 3 :(得分:-1)
我们刚刚发布了kilim 2.0的预发行版。它提供了一个光纤和actor实现(类似于quasar),并由ThreadPoolExecutor支持
限制并发任务数量的最有效方法是让一个任务充当控制器并监听邮箱(我认为quasar会调用这些通道)并保持运行任务的数量。当每个任务完成时,给邮箱发送消息
通常,使用比核心更多的线程是没有意义的