来自队列的多线程工作 - 太多工作?

时间:2017-01-06 12:03:11

标签: java multithreading queue

假设我有一个大型队列,类似10,000个对象。我想创建一个包含5个工作线程的线程池,每个线程从队列中删除一个项目并对其进行处理,直到队列为空。

我担心的是,使用我在不同地方看到的设置,我最终立即创建了10,000个工作,但是通过5个工作人员执行它们。我觉得这不是真正的可扩展 - 队列已经有10,000个项目,现在我在堆栈上还有10,000个作业(即使它们没有被主动执行,这看起来像是一个内存问题)

这似乎是这个答案的建议:https://stackoverflow.com/a/9916299/774359 - 它是" // now submit our jobs"让我担心的一部分。我是否有效地将队列转移到工作岗位上?

以下是我到目前为止的一个简短例子:

在Main()中:

ExecutorService executor = Executors.newFixedThreadPool(5);
while(!hugeQueue.isEmpty()) {
    String work = hugeQueue.remove();
    System.out.println("Creating job for " + work);
    Runnable worker = new Worker(work);
    executor.execute(worker);
}

在Worker类中:

public Worker(String itemFromQueue) { this.job = itemFromQueue; }

@Override
public void run() {
     System.out.println("Working on " + this.itemFromQueue);
     //Do actual work
}

hugeQueue包含10,000个数字时,我会看到所有10,000个"创建工作"消息,然后是所有10,000"工作"消息。我认为如果一次只创建5个作业会更好,然后他们会继续工作 - 当一个线程打开时,它会创建另一个工作然后工作。这样,堆栈上永远不会有10,000个工作。我怎么做到这一点?我是否正确地考虑了这种架构?

根据答案编辑包含更新的信息:

@ seneque的代码并没有直接编译,所以我做了一些小改动 - 不幸的是,这只是工人的创造,而不是实际的工作。

在Main()中:

int numOfThreads = 5;
BlockingQueue<Integer> hugeQueue = new LinkedBlockingQueue<>();
for(int x = 0; x < 1000; x++) { hugeQueue.add(x); }

ExecutorService executor = Executors.newFixedThreadPool(numOfThreads);
LongRunningWorker longRunningWorker = new LongRunningWorker();

for( int i = 0; i < numOfThreads ; i++ ) {
    System.out.println("Created worker #" + i);
    executor.submit(longRunningWorker);
}
System.out.println("Done");

在LongRunningWorker中:

public class LongRunningWorker implements Runnable {
    BlockingQueue<Integer> workQueue;
    void spiderExmaple(BlockingQueue<Integer> workQueue) {
        this.workQueue = workQueue;
    }

    @Override
    public void run() {
        try {
            while(workQueue.poll(3, TimeUnit.SECONDS) != null) {
                Integer work = workQueue.remove();
                System.out.println("Working on " + work);
                new Worker(work).run();
            }
        } catch (InterruptedException e) { e.printStackTrace(); }
    }
}

在工人中:

public class Worker implements Runnable{
    Integer work;
    Worker(Integer x) { this.work = x; }

    @Override
    public void run() {
        System.out.println("Finished work on " + this.work);

    }
}

1 个答案:

答案 0 :(得分:1)

一个解决方案是让你有五个线程直接轮询队列。

BlockingQueue<String> hugeQueue = ...
ExecutorService executor = Executors.newFixedThreadPool(5);
LongRunningWorker longRunningWorker = new LongRunningWorker(hugeQueue);
for( int i = 0; i < 5 ; i++ ) {
    executor.submit(longRunningWorker)
}

然后将LongRunningWorker定义为:

class LongRunningWorker(BlockingQueue<String> workQueue) extends Runnable {
    final BlockingQueue<String> workQueue;
    LongRunningWorker(BlockingQueue<String> workQueue) {
        this.workQueue = workQueue;
    }   

    public void run() {
       while((String work =  workQueue.poll(3, TimeUnit.Second) != null) {
           try {
               new Worker(work).run();
           } catch (Exception e) {
               // 
           }
        }
    }
}