Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中使用多线程时性能降低_Java_Multithreading_Concurrency - Fatal编程技术网

在java中使用多线程时性能降低

在java中使用多线程时性能降低,java,multithreading,concurrency,Java,Multithreading,Concurrency,我是多线程新手,我必须使用多线程来编写程序以提高效率。在我第一次尝试时,我写的东西产生了相反的结果。以下是我写的: class ThreadImpl implements Callable<ArrayList<Integer>> { //Bloom filter instance for one of the table BloomFilter<Integer> bloomFilterInstance = null; // Data

我是多线程新手,我必须使用多线程来编写程序以提高效率。在我第一次尝试时,我写的东西产生了相反的结果。以下是我写的:

class ThreadImpl implements Callable<ArrayList<Integer>> { 
    //Bloom filter instance for one of the table
    BloomFilter<Integer> bloomFilterInstance = null;
    // Data member for complete data access.
    ArrayList< ArrayList<UserBean> > data = null;
    // Store the result of the testing 
    ArrayList<Integer> result = null;
    int tableNo;

    public ThreadImpl(BloomFilter<Integer> bloomFilterInstance, 
                        ArrayList< ArrayList<UserBean> > data, int tableNo) {
        this.bloomFilterInstance = bloomFilterInstance;
        this.data = data;
        result  = new ArrayList<Integer>(this.data.size());
        this.tableNo = tableNo;
    }

    public ArrayList<Integer> call() {
        int[] tempResult = new int[this.data.size()];
        for(int i=0; i<data.size() ;++i) {
            tempResult[i] = 0;
        }
        ArrayList<UserBean> chkDataSet = null;
        for(int i=0; i<this.data.size(); ++i) {
            if(i==tableNo) {
                //do nothing;
            } else {
                chkDataSet = new ArrayList<UserBean> (data.get(i));
                for(UserBean toChk: chkDataSet) {
                    if(bloomFilterInstance.contains(toChk.getUserId())) {
                        ++tempResult[i];
                    }
                }
            }
            this.result.add(new Integer(tempResult[i]));
        }
        return result;
    }
}
我和jprofiler做了分析

!![这里]:(http://tinypic.com/r/wh1v8p/6)

是cpu线程的快照,其中红色表示阻塞,绿色表示可运行,黄色表示等待。我的问题是线程一次运行一个,我不知道为什么


注意:我知道这不是线程安全的,但我知道我现在只做读取操作,只想分析可以实现的原始性能增益,稍后我将实现一个更好的版本。

该进程看起来CPU受限。(无I/O、数据库调用、网络调用等)我可以想到两种解释:

  • 你的机器有多少个CPU?Java允许使用多少个如果线程在争夺同一个CPU,那么就增加了协调工作,并对同一资源提出了更多的需求
  • 整个方法运行需要多长时间?在很短的时间内,上下文切换线程中的额外工作可能会超过实际工作。解决这个问题的方法是做一份更长的工作。另外,在循环中运行它很多次,不计算前几次迭代(比如热身,它们不具有代表性)
  • 谁能告诉我错过了什么

    一种可能性是,创建线程的成本正在淹没并行计算可能带来的性能收益。我们无法确定这是否真的有可能,因为您没有在问题中包含相关代码

    另一种可能是您只有一个处理器/内核可用。线程仅在有处理器运行时运行。因此,您对线程数的线性速度的期望,只有在每个线程都有一个空闲处理器的情况下(理论上)才可能实现

    最后,由于所有线程都试图访问共享阵列,可能会出现内存争用。如果您进行了适当的同步,那么可能会增加进一步的争用。(注意:在您的示例中,我没有尝试理解算法以确定是否可能存在争用。)


    我最初的建议是分析你的代码,看看这是否提供了一些见解


    看看你衡量绩效的方式,确保你看到的不仅仅是一些标杆产品;e、 g.JVM预热效应。

    我想到了几种可能性:

    • bloomFilterInstance
      的实现(未给出)中正在进行一些同步
    • 存在大量内存分配,例如,当创建
      chkDataSet
      时,使用
      新整数
      而不是
      Integer.valueOf
      ,这似乎是
      数组列表的不必要副本。您可能会遇到内存分配的开销
    • 您可能受到CPU的限制(如果
      bloomFilterInstance#contains
      的开销很大),线程只是为CPU阻塞,而不是执行

    探查器可能有助于揭示实际问题。

    bloomFilterInstance的特征是什么?有没有可能是同步的?没有,它没有使用同步块你使用了多少线程?显示启动线程的代码。添加了创建线程的代码。添加了分析信息我有2个内核。您是否需要明确指示jvm使用2个内核??整个方法用了6112毫秒(带线程)和5334毫秒(不带多线程)。默认情况下,它应该同时使用两个内核。您能检查一下我所做的分析吗?它清楚地表明,任何时候都没有两个线程并行运行,这就是性能下降的原因。请给出一些原因,我完全不明白这一点:在程序执行的前三分之二时间里根本没有线程。最后三分之一,两个核心都在使用。您不会看到所有5个内核同时运行,因为您只有两个内核。这意味着他们必须换掉(这并不能让事情变得更快),但要回到大部分时间——前二十秒。那里发生了什么事,花了这么长时间?添加一些计时语句或类似的语句,以查看哪个方法调用占用了所有的时间。
    class MultithreadedVrsion {
        public static void main(String[] args) {
            if(args.length > 1) {
                ExecutorService es = Executors.newFixedThreadPool(noOfTables);
                List<Callable<ArrayList<Integer>>> threadedBloom = new ArrayList<Callable<ArrayList<Integer>>>(noOfTables);
                for (int i=0; i<noOfTables; ++i) {
                    threadedBloom.add(new ThreadImpl(eval.bloomFilter.get(i), 
                                                    eval.data, i)); 
                }
                try {
                    List<Future<ArrayList<Integer>>> answers = es.invokeAll(threadedBloom);
                    long endTime = System.currentTimeMillis();
                    System.out.println("using more than one thread for bloom filters: " + (endTime - startTime) + " milliseconds");
                    System.out.println("**Printing the results**");
                    for(Future<ArrayList<Integer>> element: answers) {
                        ArrayList<Integer> arrInt = element.get();
                        for(Integer i: arrInt) {
                            System.out.print(i.intValue());
                            System.out.print("\t");
                        }
                        System.out.println("");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }