1

我正在开发一个可以发送 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循环中,任务是同时运行的吗?还是一个接一个地运行?

谢谢!

4

6 回答 6

4

我在这里很困惑,在for循环中,任务是同时运行的吗?还是一个接一个地运行?

使用您发布的代码,它们将一个接一个地运行,因为(假设RequestTask是 的子类Thread您调用了run. 你应该打电话start既然您已经说过RequestTaskimplements Runnable,那么正确的代码不会调用start(它没有!)而是new Thread(task);. (但看起来您现在已经收到了关于 的好答案ExecutorService,这是另一种方法。)

假设您改为在不同的线程上调用start它们,那么是的,它们都将并行运行(尽可能在硬件上运行,等等)。

于 2012-07-23T09:03:40.760 回答
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();
于 2012-07-23T09:14:45.127 回答
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

二、或者创建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);
}
于 2012-07-23T09:13:34.157 回答
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它们将在不同线程中异步执行。

于 2012-07-23T09:17:50.087 回答
1

您正在当前线程中一一运行它们。您需要使用 ExecutorService 来同时运行它们。

于 2012-07-23T09:03:26.527 回答
0

我通常倾向于创建我的线程(或实现接口的类),然后使用 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();
}
于 2012-07-23T12:42:24.150 回答