Почему служба SingleThreaded Executor использует 4 ядра?

У меня есть следующий код, который использует однопоточную службу исполнителя, но при его запуске используются все 4 ядра на моей машине (каждое ядро ​​в среднем использует около 80%).

Вопрос в том, почему это происходит? И я не заинтересован здесь в поиске Фибоначчи на самом деле!

public class MainSimpler {
    static int N=35;
    static AtomicInteger result = new AtomicInteger(0), pendingTasks = new AtomicInteger(1);
    static ExecutorService executor;

    public static void main(String[] args) {
        executor = Executors.newSingleThreadExecutor(); 
        long before = System.currentTimeMillis();
        System.out.println("Fibonacci "+N+" is ... ");
        executor.submit(new FibSimpler(N));
        waitToFinish();
        System.out.println(result.get());
        long after = System.currentTimeMillis();        
        System.out.println("Duration: " + (after - before) + " milliseconds\n");
    }

    private static void waitToFinish() {
        while (0 < pendingTasks.get()){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executor.shutdown();
    }
}



class FibSimpler implements Runnable {
    int N;
    FibSimpler (int n) { N=n; }

    @Override
    public void run() {
        compute();
        MainSimpler.pendingTasks.decrementAndGet();
    }

    void compute() {
        int n = N;
        if (n <= 1) {
            MainSimpler.result.addAndGet(n);
            return;
        }
        MainSimpler.executor.submit(new FibSimpler(n-1));
        MainSimpler.pendingTasks.incrementAndGet();
        N = n-2;
        compute();  // similar to the F/J counterpart
    }
}

Это связано с другим вопросом мой .


person Mahdi    schedule 30.11.2012    source источник
comment
Можете ли вы опубликовать короткую, но полную программу, демонстрирующую проблему? Нам нужно увидеть FibSampler.   -  person Jon Skeet    schedule 30.11.2012
comment
Это есть в коде. Просто прокрутите вниз! :)   -  person Mahdi    schedule 30.11.2012
comment
Что касается использования ядра, то не обязательно, чтобы ваш код использовал все ядра. ОС также может использовать эти ядра. Так что ваш вопрос некорректен. Что касается вашего другого вопроса, то просто использование потоков не дает производительности, вы должны оптимизировать его для наилучшего использования в параллельной среде. И алгоритм должен быть таким, который можно было бы выполнять параллельно.   -  person Narendra Pathai    schedule 30.11.2012
comment
Ваш другой комментарий не очень информативен. Что бы ни использовала ОС, это не увеличивает загрузку ЦП моей программы, не так ли ??   -  person Mahdi    schedule 30.11.2012
comment
@Mahdi Только что попробовал на моей машине, и я получил 35% общей загрузки ЦП (4 ядра). В вашей программе есть как минимум 2 потока (основной поток и поток исполнителя).   -  person assylias    schedule 30.11.2012
comment
@assylias: основной поток в основном спит. Вы имеете в виду, что исполнитель использует другой поток рядом со своим рабочим потоком?   -  person Mahdi    schedule 30.11.2012
comment
@Mahdi Махди - я предполагаю, что должно быть очень сложно дать приемлемые для вас ответы. Пожалуй, даже не стоит пытаться...   -  person Stephen C    schedule 30.11.2012


Ответы (1)


Только что попробовал на своей машине, и я получил 35% общей загрузки ЦП (4 ядра). Обратите внимание, что в вашей программе есть как минимум 2 потока (основной поток и поток исполнителя).

Однако, если я увеличу N до 100, загрузка ЦП увеличится до 90+%, потому что много времени тратится на полные сборщики мусора (а я работал с 2 ГБ кучи).

Таким образом, похоже, что ваш единственный поток становится слишком занятым, и задачи начинают накапливаться, ожидая выполнения.

Вы можете попробовать запустить код со следующими параметрами JVM: -XX:+PrintGC

Вывод на моей машине выглядит так:

[GC 511999K->465632K(1962688K), 1,0286778 с]
[GC 977632K->922984K(1962688K), 1,1999209 с]
[GC 1434984K->1407984K(1962688K), 1,24682K1, 90 [secFll 1373358K (1962688K), 9.8320408 SEC)
[Full GC 1885358K-> 1822040K (1962688K), 7.5170472 SEC]
[Full GC 1877375K-> 1870974K (1962688K), 7.6635945 сек. Полный сборщик мусора 1877374K->1876550K(1962688K), 7,6705722 с]
[Полный сборщик мусора 1877374K->1877272K(1962688K), 7,8381579 с]
[Полный сборщик мусора 1877372K->1877358 с), 02,826K с(1607358 с]

person assylias    schedule 30.11.2012