【问题标题】:Multi thread is slower than one [duplicate]多线程比一个慢[重复]
【发布时间】:2014-12-11 02:08:04
【问题描述】:

我正在使用多线程编写应用程序来计算 txt 文件中的字符数。 文件包含 10 000 000 个字符。 10 000 行和 1 000 列。

已编辑
关于问题的第一部分: Prevoius 的问题是关于线程的,我以错误的方式使用了thread.join();

第二部分: 你能帮我提高性能和安全性吗?这是我的代码(需要使用信号量):

public class MultiThread implements Runnable {

    HashMap<String, AtomicInteger> asciiMap = Maps.newHashMap();
    LinkedList<String> asciiLines = ReadDataFromFile.lines;
    Semaphore mutex = new Semaphore(1);
    AtomicInteger i = new AtomicInteger(0);
    int index;

    @Override
    public void run() {

        long actual = 0;
        try {
            Calculate calculate = new Calculate();
            long multiStart = System.currentTimeMillis();

            Thread first = new Thread(calculate);
            Thread second = new Thread(calculate);
            Thread third = new Thread(calculate);

            first.start();
            second.start(); 
            third.start();

            first.join();
            second.join();
            third.join();

            long multiEnd = System.currentTimeMillis();
            actual = multiEnd - multiStart;

        } catch (InterruptedException ex) {
            Logger.getLogger(MultiThread.class.getName()).log(Level.SEVERE, null, ex);
        }

        int sum = 0;
        for (Map.Entry<String, AtomicInteger> entry : asciiMap.entrySet()) {
            System.out.println("Char: " + entry.getKey() + " , number: " + entry.getValue());
            sum = sum + entry.getValue().get();
        }

        System.out.println("Time: " + actual);

    }

    int increment() {

        try {
            mutex.acquire();
            index = i.incrementAndGet();
            mutex.release();

        } catch (InterruptedException ex) {
            Logger.getLogger(MultiThread.class.getName()).log(Level.SEVERE, null, ex);
        }
        return index;
    }

    public class Calculate implements Runnable {

        public Calculate() {
        }

        @Override
        public void run() {

            while (i.get() < asciiLines.size()) {
                for (String oneCharacter : asciiLines.get(i.get()).split("")) {
                    if (asciiMap.containsKey(oneCharacter)) {
                        asciiMap.replace(oneCharacter, new AtomicInteger(asciiMap.get(oneCharacter).incrementAndGet()));
                    } else {
                        asciiMap.put(oneCharacter, new AtomicInteger(1));
                    }
                }
                i = new AtomicInteger(increment());
            }
        }
    }

}

LinkedList 中的每个元素都包含一行(1000 个字符)。

【问题讨论】:

  • 你为什么不试试 1,2,4 线程。你确定你正在并行运行所有线程吗? first.join()second.start() 之前执行
  • 你试过Fork/Join的方法吗?
  • 除了你的 hashmap 实现选择错误 - 它不是线程安全的,而且你对 atomicinteger 的使用很糟糕。
  • @TomaszSzuba 如何正确实现它?
  • 编辑您的问题时请考虑周全。不要更改它以使其不再匹配其标题或使答案不再适合。其他人可能有与您相同的问题,他们可能会找到您的问题及其答案。我们希望您的原始问题和答案在发生这种情况时仍然有意义。

标签: java multithreading performance semaphore


【解决方案1】:

您的代码绝对没有多线程。 Thread.join 表示等到该线程完成执行,然后继续当前执行线程。现在,您的代码正在串行执行每个线程。您希望交替调用开始和加入。

Thread first = new Thread(calculate);
Thread third = new Thread(calculate);
Thread second = new Thread(calculate);

first.start();
second.start();
third.start();

first.join();
second.join();
third.join();

【讨论】:

  • 多么愚蠢的错误!
  • 这就是为什么您应该始终使用ExecutorService
  • 当然,这就是解决方案!但是线程安全吗?
猜你喜欢
  • 2012-09-05
  • 1970-01-01
  • 1970-01-01
  • 2020-08-15
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多