使用Java Executor接口的多线程方法 - java

我正在尝试使用executor接口实现多线程方法,其中我在主类中产生了多个线程

class Main
{
    private static final int NTHREADS = 10;

    public static void main(String[] args)
    {
        .........
        String str = createThreads(document);
        .............
    }


    public String createThreads(String docString)
    {

        ........
        .......
        Map<String,String> iTextRecords = new LinkedHashMap<String, String>();
        if(!iText.matches(""))
        {
            String[] tokenizedItext = iText.split("\\^");
            ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
            for(int index = 0 ;index < tokenizedItext.length;index++)
            {
                Callable<Map<String,String>> worker = null;
                Future<Map<String,String>> map = null;
                if(tokenizedItext[index].matches("^[0-9.<>+-= ]+$") || tokenizedItext[index].matches("^\\s+$"))
                {
                    iTextRecords.put(tokenizedItext[index],tokenizedItext[index]);
                }
                else
                {
                    worker = new MultipleDatabaseCallable(tokenizedItext[index],language);
                    map = executor.submit(worker);
                    try
                    {
                        iTextRecords.putAll(map.get());
                    }
                    catch(InterruptedException ex)
                    {
                        ex.printStackTrace(System.out);
                    }
                    catch(ExecutionException ex)
                    {
                        ex.printStackTrace(System.out);
                    }
                }

            }

            executor.shutdown();
            // Wait until all threads are finish
            while (!executor.isTerminated())
            {

            }

    }
}

Callable类为

class MultipleDatabaseCallable implements Callable<Map<String,String>> 
{
    @Override
    public Map<String, String> call() throws Exception {

        System.out.println("Entering: "+Thread.currentThread().getName());
        Map<String,String> map = new HashMap<String,String>();
        for(int i =0;i<50000;i++)
        {
            for(int i1 = 0 ;i1<5000;i1++)
            {
                for(int i2 =0;i2 <500;i2++)
                {

                }
            }
        }
        System.out.println("Exiting: "+Thread.currentThread().getName());
        return map;
    }
}

我得到的输出是

Entering: pool-1-thread-1
Exiting: pool-1-thread-1
Entering: pool-1-thread-2
Exiting: pool-1-thread-2
Entering: pool-1-thread-3
Exiting: pool-1-thread-3
Entering: pool-1-thread-4
Exiting: pool-1-thread-4
Entering: pool-1-thread-5
Exiting: pool-1-thread-5
Entering: pool-1-thread-6
Exiting: pool-1-thread-6

在查看输出时,似乎一次只在调用方法中输入一个线程,而其他线程仅在存在前一个线程时才进入。但是,预计多个线程应该输入并执行call()方法。另外,当我通过使NTHREADS = 1执行相同的程序时,所花费的时间与NTHREADS = 10所花费的时间相同。

所以看起来该应用程序的运行情况与单线程应用程序一样好。请提出我在实现过程中出现的问题。

谢谢

参考方案

您打电话的时候

                map = executor.submit(worker);

在这种情况下,返回的map值为Future。意味着在可调用对象返回一个值之前,它没有值。现在当你打电话

                    iTextRecords.putAll(map.get());

发生的情况是当前线程块(在map.get()内部)等待可调用对象返回(在另一个线程中)。

由于您始终等待可调用对象完成(每个map.get()),然后再提交一个新对象(每个executor.submit()),因此可以强制执行观察到的顺序执行。

为了并行执行任务,必须在第一次调用get之前将其全部启动。例如,您可以创建一个ArrayList<Future<Map<String,String>>> futures = ...然后

  futures.add(executor.submit(worker)); 

提交任务(不需要map变量)并创建第二个循环(在for(int i ...)循环之后):

 for(Future<Map<String,String>> f: futures) {
     iTextRecords.putAll(f.get);
 }

使用Java RMI调用Python方法 - java

我有一个通过Python web2py创建的远程方法。如何测试和调用Java中的方法?我能够测试该方法是否实现@service.xmlrpc,但是如何测试该方法是否实现@service.run? 参考方案 如果您能做到,我会感到惊讶。 Java RMI需要Java对等体。

获取远程机器的系统信息(使用Java) - java

正如问题的标题所言,我想使用Java获取远程系统的系统信息(例如OS名称,版本等)。但是,在任何人回答这个问题之前,我只想问一下这是否可能,如果可以,那么如何?还有一个问题是,这对于基于Unix和基于Windows的系统都应适用。我尝试搜索Internet,但是(几乎)空白。编辑:Java应用程序将是一个桌面应用程序,它必须具有凭据才能登录到远程系统,但不会…

使用Java 8流处理null属性,并使用lambda表达式进行排序 - java

让我们考虑一个仅包含一个Parent属性的Integer类。我创建了6个父类对象,属性值是100, 20, 300, 400, 500, null。现在,我将所有对象添加到列表中(列表名称为list)。然后,我想获取其属性值大于100的对象。为此,我使用了Java 8流。Predicate<Entity> predicate = e -> …

使用java.util.properties存储ArrayList和HashMap - java

如何使用ArrayList存储HashMap和/或java.util.properties变量?如果不可能,可以使用其他什么类来存储应用程序配置? 参考方案 如果只需要将集合序列化为字符串,我强烈建议XStream。它使用反射将类序列化为XML。如果默认行为对您要序列化的类不起作用,则有文档,但是到目前为止,以下内容对我而言一直有效:XStream xstr…

使用Java 8流的if-else条件 - java

场景:在某些情况下,我需要使用Java 8流API根据某些字段条件为对象的List设置一些值。下面是对象User的示例。public class User{ private int id; private String name; private String text; private boolean isActive; } 这是我制定的代码List<…