我正在尝试同时处理多个csv。我的代码如下所示:

public class CSVMain{

private static int count = 3;

public static void main(String[] a){

    ExecutorService e = Executors.newFixedThreadPool(300);
    for(int i=0;i<count;i++) e.execute(new WebRunner("http://some.host.com"));
    e.shutdown();

}

static class WebRunner implements Runnable{

    private final String url;

    public WebRunner(String url) {
        this.url = url;
    }

    @Override
    public void run() {

        try {

            long now = System.currentTimeMillis();
            URL MyUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) MyUrl.openConnection();
            conn.connect();

            IOUtils.toByteArray(MyUrl.openStream());

            System.out.println(new DateTime().toString("HH:mm:ss,SSS") + " finish thread" + Thread.currentThread().getId() + " in " + (System.currentTimeMillis() - now));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

}


如果将静态count变量设置为1,则将在600-700毫秒的连接时间内完成。当它为2时,我会得到大约1100-1400毫秒,当它为3时,我会得到1700-1900毫秒,依此类推。

统计数据感觉是连续的,而不是并行的。

我在这里想念什么吗?

最佳答案

有几点有助于这一点。

首先,您要测量单个Runnable的运行时间,而不是顺序运行(即,运行WebRunner三次,一次又一次)与并发运行(将它们分配给线程)的总运行时间池,就像您在这里一样)。

另一个重要的事实是并发并不意味着事情将并行执行。 Concurrency is not parallelism他们可能会或可能不会。并发也是高度不确定的。也就是说,什么时候允许线程运行以及它们运行多长时间取决于很多因素,包括操作系统。根据情况,它们甚至可能最终顺序运行(无论线程池的大小如何)。它们甚至看起来似乎是并行执行的,但是它们可能以循环方式执行,而并发和切换的开销却没有太大的好处。并发有很多微妙之处。有关深入的指南,最好的资源是this book

同样,即使任务确实并行运行,性能也会受到其他限制。您可能具有有限的网络带宽,并且当任务并行运行时,它们可能最终会争夺该有限的资源。计算能力和内存也是如此。

另一个非常重要的事情是,您正在做的是微基准测试的幼稚版本。为了获得更可靠的基准统计数据,您可能应该使用类似The JMH framework之类的方法。这是有关pitfalls of naive java benchmarkingan article on JMH的相关文章

TL; DR;版本是:在没有很多严格要求的情况下,请勿尝试为并发应用程序的性能分配含义。

10-04 23:16
查看更多