Java - Язык:Как масштабировать потоки в соответствии с ядрами процессора?

StackOverflow https://stackoverflow.com/questions/1980832

  •  22-09-2019
  •  | 
  •  

Вопрос

Я не очень хороший java-программист, это просто мое хобби, но я горю желанием знать больше, чем обычные вещи.

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

но я не хочу иметь фиксированное количество потоков, работающих над этим, а вместо этого количество потоков, соответствующее количеству ядер процессора.и моя проблема в том, что я не смог найти простой учебник в Интернете для этого.все, что я нашел, - это примеры с фиксированными потоками.

Итак, не могли бы вы помочь мне ссылкой на хорошее учебное пособие или привести простой и наглядный пример?Это было бы действительно здорово :)

Это было полезно?

Решение

Вы можете определить количество процессов, доступных виртуальной машине Java, используя статический метод времени выполнения, Доступные процессоры.После того как вы определили количество доступных процессоров, создайте это количество потоков и соответствующим образом разделите свою работу.

Обновить:Чтобы еще раз уточнить, Поток - это просто объект в Java, поэтому вы можете создать его точно так же, как вы бы создали любой другой объект.Итак, предположим, что вы вызываете описанный выше метод и обнаруживаете, что он возвращает 2 процессора.Потрясающе.Теперь вы можете создать цикл, который генерирует новый поток, разделяет работу для этого потока и запускает поток.Вот некоторый псевдокод, чтобы продемонстрировать, что я имею в виду:

int processors = Runtime.getRuntime().availableProcessors();
for(int i=0; i < processors; i++) {
  Thread yourThread = new AThreadYouCreated();
  // You may need to pass in parameters depending on what work you are doing and how you setup your thread.
  yourThread.start();
}

Для получения дополнительной информации о создании вашего собственного потока, перейдите к этому руководству.Кроме того, вы, возможно, захотите взглянуть на Объединение потоков для создания потоков.

Другие советы

Вы, вероятно, тоже захотите взглянуть на java.util.concurrent framework для этого материала.Что - то вроде:

ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// Do work using something like either
e.execute(new Runnable() {
        public void run() {
            // do one task
        }
    });

или

    Future<String> future = pool.submit(new Callable<String>() {
        public String call() throws Exception {
            return null;
        }
    });
    future.get();  // Will block till result available

Это намного приятнее, чем справляться с вашими собственными пулами потоков и т.д.

У Дуга Ли (автора параллельного пакета) есть этот документ, который может оказаться актуальным:http://gee.cs.oswego.edu/dl/papers/fj.pdf

Фреймворк Fork Join был добавлен в Java SE 7.Ниже приведено еще несколько ссылок:

http://www.ibm.com/developerworks/java/library/j-jtp11137/index.html Статья Брайана Гетца

http://www.oracle.com/technetwork/articles/java/fork-join-422606.html

Вариант 1:

newWorkStealingPool Новый рабочий пакет От Executors

public static ExecutorService newWorkStealingPool()

Создает пул потоков, забирающий работу, используя все доступные процессоры в качестве целевого уровня параллелизма.

С помощью этого API вам не нужно передавать количество ядер в ExecutorService.

Реализация этого API из grepcode ( код grepcode )

/**
     * Creates a work-stealing thread pool using all
     * {@link Runtime#availableProcessors available processors}
     * as its target parallelism level.
     * @return the newly created thread pool
     * @see #newWorkStealingPool(int)
     * @since 1.8
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

Вариант 2:

Новый фиксированный пул потоков API из Executors или other newXXX constructors, который возвращает ExecutorService

public static ExecutorService newFixedThreadPool(int nThreads)

замените nThreads на Runtime.getRuntime().availableProcessors()

Вариант 3:

Потоковый пул - исполнитель

public ThreadPoolExecutor(int corePoolSize,
                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue<Runnable> workQueue)

пройти Runtime.getRuntime().availableProcessors() в качестве параметра для maximumPoolSize.

Стандартным способом является метод Runtime.getRuntime().Available Processors().На большинстве стандартных процессоров вы вернете здесь оптимальное количество потоков (которое не является фактическим количеством ядер процессора).Следовательно, это то, что вы ищете.

Пример:

ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

НЕ забудьте закрыть службу исполнителя подобным образом (иначе ваша программа не завершится).:

service.shutdown();

Вот лишь краткое описание того, как настроить будущий MT-код (оффтопик, для иллюстрации):

CompletionService<YourCallableImplementor> completionService = 
    new ExecutorCompletionService<YourCallableImplementor>(service);
    ArrayList<Future<YourCallableImplementor>> futures = new ArrayList<Future<YourCallableImplementor>>();
    for (String computeMe : elementsToCompute) {
        futures.add(completionService.submit(new YourCallableImplementor(computeMe)));
    }

Затем вам нужно отслеживать, сколько результатов вы ожидаете, и извлекать их следующим образом:

try {
  int received = 0;
  while (received < elementsToCompute.size()) {
     Future<YourCallableImplementor> resultFuture = completionService.take(); 
     YourCallableImplementor result = resultFuture.get();
     received++; 
  }
} finally {
  service.shutdown();
}

В классе Runtime существует метод, называемый Available Processors() .Вы можете использовать это, чтобы выяснить, сколько процессоров у вас есть.Поскольку ваша программа привязана к процессору, вы, вероятно, хотели бы иметь (не более) одного потока на доступный процессор.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top