并发/多线程何时有助于提高性能?

时间:2016-03-24 12:20:49

标签: java multithreading performance concurrency

我一直计划在学习之后在项目中使用并发性确实已经增加了很多。 现在我在多线程或并发方面没有太多工作,所以决定在实际项目中使用它之前学习并有一个简单的概念证明。
以下是我尝试过的两个例子:

1. With use of concurrency

    public static void main(String[] args) 

    {
        System.out.println("start main ");

        ExecutorService es = Executors.newFixedThreadPool(3);
        long startTime = new Date().getTime();
        Collection<SomeComputation> collection = new ArrayList<SomeComputation>();
        for(int i=0; i< 10000; i++){
            collection.add(new SomeComputation("SomeComputation"+i));
        }
        try {
            List<Future< Boolean >> list = es.invokeAll(collection);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\n end main "+(new Date().getTime() - startTime));
    }

2. Without use of concurrency

        public static void main(String[] args) {

          System.out.println("start main ");
          long startTime = new Date().getTime();
          Collection<SomeComputation> collection = new ArrayList<SomeComputation>();
          for(int i=0; i< 10000; i++){
          collection.add(new SomeComputation("SomeComputation"+i));
        }
        for(SomeComputation sc:collection)
        {
        sc.compute();
        }
        System.out.println("\n end main "+(new Date().getTime() - startTime));
        }

    Both share a common class

        class SomeComputation implements Callable<Boolean>
        {
            String name;
            SomeComputation(String name){this.name=name;}
            public Boolean compute()
            {
                someDumbStuff();
                return true;
            }

            public Boolean call()
            {
                someDumbStuff();
                return true;
            }

            private void someDumbStuff()
            {
                for (int i = 0;i<50000;i++)
                {
                    Integer.compare(i,i+1);
                }
                System.out.print("\n done with "+this.name);
            }
        }

现在每种方法经过20多次运行后的分析 并发的第一个平均需要451毫秒 没有并发的第二个平均需要290毫秒 现在我了解到这取决于配置,操作系统,版本(java 7)和处理器。 但两种方法都是一样的。 还了解到,当计算量很大时,并发成本是可以承受的。但是这一点对我来说并不清楚。
希望有人能帮我理解这一点 PS:我试过找到类似的问题,但可以找到这种类型。如果你这样做,请发表评论。

3 个答案:

答案 0 :(得分:2)

并发至少有两个不同的目的:1)性能,2)代码简单(就像1000个Web请求的监听器)。

如果您的目的是性能,则无法获得比您投入使用的硬件核心数更多的加速。 (只有当线程受CPU限制时才会这样。) 而且,每个线程都有很大的启动开销。 因此,如果您在4核计算机上启动1000个线程,则可能比4倍速度更好,但与此相比,您有1000个线程启动成本。

答案 1 :(得分:1)

当线程共享相同的数据源时,需要获得一致性 因此,当某个线程正在使用此源时,其他线程必须等到它 完成工作比他们有访问 所以你需要学习同步的方法和bluck或类似的东西 对不起我的英语阅读这个turial它很有帮助 https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

答案 2 :(得分:1)

正如其中一个答案中所提到的,并发的一个用途是使代码简单,即存在逻辑上并发的某些问题,因此无法以非并发方式对这些问题进行建模,如生产者 - 消费者问题,听取网络请求等

除此之外,并发程序只有在能够为您保存 CPU Cycles 时才会增加性能,即目标是始终保持CPU或CPU忙碌而不浪费其周期意味着你让你的CPU在你的程序忙于某些事情时做一些有用的事情 - 非CPU任务,比如等待磁盘I / O,等待锁定,睡眠,GUI应用程序用户等等 - 这些时间只是增加你的时间总程序运行时间。

所以问题是,当你的程序没有使用它时你的CPU在做什么?我可以在那段时间内完成我的程序的一部分并在另一个线程中隔离等待部分吗?现在有一天,大多数现代系统都是多处理器和多核系统,如果程序不是并发的话,还会导致浪费。

您编写的示例是在内存中执行所有处理而不进入任何等待状态,因此您不会看到很多增益,但只会丢失设置线程和上下文切换。

尝试通过点击数据库来测量性能,获取100万条记录,处理这些记录,然后再将这些记录保存到数据库。同时进行顺序和小批量同时进行,因此您会注意到性能差异,因为数据库操作是磁盘密集型的,当您正在读取或写入数据库时​​,您实际上正在执行磁盘I / O并且CPU可以自由地浪费其周期那时。

在我看来,良好的并发候选者是长期运行的任务,涉及上面提到的等待操作之一,否则你看不到多少收益。需要一些后台任务的程序< / strong>也是并发的良好候选者。

并发性不必与CPU的多任务混淆,即同时在同一CPU上运行不同的程序时。

希望它有所帮助!!