我有一段类似于以下内容的代码:
final int THREADS = 11;
BlockingQueue<Future<Long>> futureQueue = new ArrayBlockingQueue<Future<Long>>(THREADS);
for (int i = 0; i < end; i++, count++) {
futureQueue.put(executor.submit(MyRunnable));
}
//Use queued results
我如何重构这个以使其更多并发?我在这里监督有什么微妙之处吗?
更新
每个Runnable都应该向服务器发送大量的HTTP请求以进行压力测试。我是否在正确的轨道上?
答案 0 :(得分:3)
我会用
static final int THREADS = Runnable.getRuntime().availableProcesses();
ExecutorService service = Executors.newFixedThreadPool(THREADS);
List<Future<Long>> futureQueue = new ArrayList<Future<Long>>(end);
for (int i = 0; i < end; i++)
futureQueue.add(executor.submit(new MyRunnable()));
您正在使用有界队列,如果end > THREADS
它将停止。
每个Runnable都应该向服务器发送大量的HTTP请求以进行压力测试。我是否在正确的轨道上?
在这种情况下,我将使用以下代码,因为您的代码是IO而不是CPU绑定。
ExecutorService service = Executors.newCachedThreadPool();
如果您拥有超过1000个线程,您可能会从使用NIO中受益,但这只会使您的负载测试器更高效,但这会使代码更加复杂。 (如果您认为这很难,那么编写高效且正确的选择器代码很多更难)
在多台机器上运行测试仪会产生更大的不同。
答案 1 :(得分:3)
使用线程在您的情况下效果不佳。当您拥有CPU密集型作业时,线程池可以很好地工作。在您的情况下,您有一个IO密集型作业 - 它不受您拥有的CPU数量的限制,而是受您可以发送的网络数据包数量的限制。
在这种情况下,NIO中的课程是你的朋友。创建数百个连接并使用NIO selectors查看哪个连接已准备好接收更多数据。
使用这种方法,根本不需要线程;一个CPU核心足以填满GBit以太网连接(~100MB / s)。
[编辑] 当然,您可以创建数百个线程来尝试填充IO通道。但这有一些缺点:
对于像这样的任务,像Akka这样的框架更适合,因为它避免了所有这些问题,并且使用起来比线程更简单。