主线程消费者和其他线程生成器

时间:2017-09-26 20:03:30

标签: java multithreading synchronization

我的问题是,我有1000条记录的数据集。我想要3个线程来处理这样的数据, thread1从记录1到300,thread2从301到600,依此类推。一个线程可以发出请求并一次获取50条记录,创建一个对象并将其放入队列中。 主线程将同时从队列中读取数据。

下面是代码,我面临的问题是recordRead变量告诉线程应该从哪里开始读取记录。 但是我如何为每个线程设置不同的值,例如对于thread1,它应该是0,recordsToRead应该是300,对于thread2,recordRead应该是300,而recordToRead应该是300 + 300 = 600,对于最后一个线程,它应该是600并且最多结束。 页大小= 50 pagesize,recordRead和recordToRead都是属于主类和主线程的变量。

    ExecutorService service = Executors.newFixedThreadPool(nThreads);
    while(nThreads > 0) {
        nThreads--;
        service.execute(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub

                do {
                    int respCode = 0;
                    int RecordsToRead = div;
                    JSONObject jsObj = new JSONObject();
                    jsObj.put("pagesize", pageSize);
                    jsObj.put("start", recordsRead);
                    jsObj.put("searchinternalid", searchInternalId);

                    try {
                        boolean status = req.invoke(jsObj); 
                        respCode = req.getResponseCode();

                    } catch (Exception e) {         
                        req.reset();
                        e.printStackTrace();
                        return true;
                    }
                    JSONObject jsResp = req.getResponseJson();
                    //here jsResp will be added to ArrayBlockingQueue.

                    req.reset();
                }while(!isError && !isMaxLimit && recordsRead < RecordsToRead);

            }

        });
    }

此循环后将是读取队列的主线程代码。 如何为所有线程设置recordsRead和recordToread。

如何使主线程等待至少一个线程在队列中插入一个对象。

1 个答案:

答案 0 :(得分:0)

我在你的定义中看到了两个问题。第一个问题是执行并行块计算,第二个问题是从中创建连续的管道。让我们从第一个问题开始。要使用预定义大小进行并行计算,最好的选择fmpv将使用fork-join框架。不仅是性能(工作窃取真的很有效),而且还因为代码更简单。但是因为你对我来说只限于3个线程,所以直接使用线程似乎也是有效的。您可以通过这种方式实现您想要的任何内容:

    final int chunkSize = 300;
    //you can also use total amount of job
    //int totalWork = 1000 and chunk size equals totalWork/threadsNumber
    final int threadsNumber = 3;

    Thread[] threads = new Thread[threadsNumber];

    for (int ii = 0; ii < threadsNumber; ii++) {
        final int i = ii;

        threads[ii] = new Thread(() -> {
           //count your variable according the volume
            // for example you can do so
            int chunkStart = i * chunkSize; 
            int chunkEnd = chunkStart + chunkSize;
            for(int j = chunkStart; j < chunkEnd; j++) {
              //object creation with necessary proprs
              //offer to queue here
            }
        });

        threads[ii].start();
    }

    //your code here
    //take here

    for (int ii = 0; ii < threadsNumber; ii++) {
        try {
         //this part is only as example
         //you do not need it                
         //here if you want you can also w8 for completion of all threads
            threads[ii].join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

现在关于消费的第二个问题。对于这个puprose,您可以使用例如ConcurrentLinkedBlockingQueue(http://www.jgroups.org/javadoc/org/jgroups/util/ConcurrentLinkedBlockingQueue.html)。在生产者线程中提供商品并在main中使用take方法。

但说实话,我仍然没有得到你问题的原因。您想创建连续管道还是只进行一次性计算?

我还建议你学习这门课程:https://www.coursera.org/learn/parallel-programming-in-java/home/welcome。 这将帮助您准确解决您的问题并提供各种解决方案。还有并发和分布式计算课程。