我正在开发一个程序,可以发送http请求来获取文档。 我已经填写了包含所有请求项的队列:
Queue<RequestItem> requestItems = buildRequest4Docs();
然后,
int threadNum = requestItems.size();
//ExecutorService exs = Executors.newFixedThreadPool(threadNum);
for (int i = 0; i < threadNum; i++) {
ResponseInterface response = new CMSGOResponse();
RequestTask task = new RequestTask(requestItems.poll(), this, response);
task.run();
//exs.execute(new RequestTask(requestItems.poll(), this, response));
}
//exs.shutdown();
我很困惑,在for循环中,任务是否同时运行?或者任务一个接一个地运行?
谢谢!
答案 0 :(得分:4)
我很困惑,在for循环中,任务是否同时运行?或者任务一个接一个地运行?
使用您发布的代码,它们将逐个运行,因为(假设您已调用RequestTask
是Thread
的子类)run
。 您应该致电现在您说start
。RequestTask
实施Runnable
,正确的代码不会调用start
(它没有'有一个!)而是new Thread(task);
。 (但看起来你现在收到了关于ExecutorService
的好答案,这是另一种方法。)
假设你调用而不是在不同的线程上启动它们,那么是的,它们都将并行运行(尽可能多地在硬件上运行)。 / p>
start
答案 1 :(得分:4)
现在你获得它的方式将逐个执行任务。如果您取消现在获得的代码作为注释并对行RequestTask task = new RequestTask(requestItems.poll(), this, response);
和task.run();
进行注释,您将获得并发执行。
因此,对于并发执行,它必须如下所示:
int threadNum = requestItems.size();
ExecutorService exs = Executors.newFixedThreadPool(threadNum);
for (int i = 0; i < threadNum; i++) {
ResponseInterface response = new CMSGOResponse();
exs.execute(new RequestTask(requestItems.poll(), this, response));
}
exs.shutdown();
while (! exs.isTerminated()) {
try {
exs.awaitTermination(1L, TimeUnit.DAYS);
}
catch (InterruptedException e) {
// you may or may not care here, but if you truly want to
// wait for the pool to shutdown, just ignore the exception
// otherwise you'll have to deal with the exception and
// make a decision to drop out of the loop or something else.
}
}
除了我的建议,您不会将使用ExecutorService
创建的线程数量绑定到您需要工作的任务量。将其连接到主机系统的处理器数量通常是更好的方法。要获得处理器使用量:Runtime.getRuntime().availableProcessors()
在像这样初始化的执行程序服务中,您放置了队列中的项目。但是,如果没有获取总大小,则可以很好地工作,而不是轮询Queue
,直到它不返回其他数据。
我的提案的最终结果可能如下:
final int threadNum = Runtime.getRuntime().availableProcessors();
final ExecutorService exs = Executors.newFixedThreadPool(threadNum);
while (true) {
final RequestItem requestItem = requestItems.poll();
if (requestItem == null) {
break;
}
final ResponseInterface response = new CMSGOResponse();
exs.execute(new RequestTask(requestItem , this, response));
}
exs.shutdown();
答案 2 :(得分:2)
目前你正在顺序运行你的线程,你有两种方法来运行线程。(假设RequestTask扩展了Thread)
I.创建线程对象并调用start()
方法。
RequestTask task = new RequestTask(requestItems.poll(), this, response);
task.start(); // run() method will be called, you don't need to call it
II.Or创建ExecutorService
ExecutorService pool = Executors.newFixedThreadPool(poolSize);
//....
for (int i = 0; i < threadNum; i++) {
ResponseInterface response = new CMSGOResponse();
RequestTask task = new RequestTask(requestItems.poll(), this, response);
pool.execute(task);
}
答案 3 :(得分:1)
您正在当前线程中逐个运行它们。您需要使用ExecutorService同时运行它们。
答案 4 :(得分:1)
I am confused here, in the for loop,does the tasks run simultaneously? Or the tasks run one by one?
任务将在同一个线程中执行,即one by one
,因为您正在调用run()
而不是start
,它将不会在新线程中运行任务。
int threadNum = requestItems.size();
ExecutorService exs = Executors.newFixedThreadPool(threadNum);
ResponseInterface response = new CMSGOResponse();
RequestTask task = new RequestTask(requestItems.poll(), this, response);
exs.execute(task );
exs.shutdown();
在上面的案例中,任务将在新线程中执行,只要您将10个不同的任务分配给ExecutorService
,它们就会在不同的线程中异步执行。
答案 5 :(得分:0)
我通常倾向于创建我的Threads(或实现Interface的类),然后使用start()方法启动它们。
在你的情况下,由于RequestTask实现了Runnable,你可以像这样添加一个start()方法:
public class RequestTask implements Runnable {
Thread t;
boolean running;
public RequestTask() {
t = new Thread(this);
}
public void start() {
running = true; // you could use a setter
t.start();
}
public void run() {
while (running) {
// your code goes here
}
}
}
,然后:
int threadNum = requestItems.size();
RequestTask[] rta = new RequestTask[threadNum];
// Create the so-called Threads ...
for (int i=0;i<threadNum;i++) {
rta[i] = new RequestTask(requestItems.poll(), this, new CMSGOResponse());
}
// ... THEN launch them
for (int i=0;i<threadNum;i++) {
rta[i].start();
}