Pergunta

Não sou um bom programador Java, é apenas o meu hobby, mas estou ansioso para saber mais do que a média.

Quero resolver um problema matemático com vários tópicos em Java. Meu problema de matemática pode ser separado em unidades de trabalho, que eu quero ter resolvido em vários threads.

Mas não quero ter uma quantidade fixa de encadeamentos funcionando nele, mas uma quantidade corporativa de encadeamentos para a quantidade de núcleos da CPU. E meu problema é que não consegui encontrar um tutorial fácil na Internet para isso. Tudo o que encontrei são exemplos com roscas fixas.

Então, você poderia me ajudar com um link para um bom tutor ou poderia me dar um exemplo fácil e bom? Isso seria muito bom :)

Foi útil?

Solução

Você pode determinar o número de processos disponíveis para a máquina virtual Java usando o método estático de tempo de execução, Disponível PROCESSORES. Depois de determinar o número de processadores disponíveis, crie esse número de threads e divida seu trabalho de acordo.

Atualizar: Para esclarecer ainda mais, um thread é apenas um objeto em Java, para que você possa criá -lo como criaria qualquer outro objeto. Então, digamos que você chama o método acima e descobre que ele retorna 2 processadores. Incrível. Agora, você pode criar um loop que gera um novo thread e divide o trabalho para esse thread e dispara o thread. Aqui está alguns psuedocode para demonstrar o que quero dizer:

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();
}

Para mais informações sobre como criar seu próprio tópico, Vá para este tutorial. Além disso, você pode querer olhar para Agrupamento de threads Para a criação dos threads.

Outras dicas

Você provavelmente deseja olhar para a estrutura java.util.Concurrent para essas coisas também. Algo como:

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

ou

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

Isso é muito melhor do que lidar com seus próprios pools de threads etc.

Doug Lea (autor do pacote simultâneo) tem este artigo que pode ser relevante:http://gee.cs.oswego.edu/dl/papers/fj.pdf

A estrutura de junção do garfo foi adicionada ao Java SE 7. Abaixo estão mais algumas referências:

http://www.ibm.com/developerworks/java/library/j-jtp11137/index.htmlArtigo de Brian Goetz

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

Opção 1:

Newworkstealingpool a partir de Executors

public static ExecutorService newWorkStealingPool()

Cria um pool de linhas de roubo de trabalho usando todos os processadores disponíveis como seu paralelismo de destino.

Com esta API, você não precisa passar o número de núcleos para ExecutorService.

Implementação desta API de 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);
    }

Opção 2:

newfixedThreadpool API de Executors ou other newXXX constructors, que retorna ExecutorService

public static ExecutorService newFixedThreadPool(int nThreads)

Substitua o NTHREADS por Runtime.getRuntime().availableProcessors()

Opção 3:

ThreadpoolExecutor

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

passar Runtime.getRuntime().availableProcessors() como parâmetro para maximumPoolSize.

O Way Standard é o método Runtime.GetRuntime (). Na maioria das CPUs padrão, você retornará a contagem ideal de roscas (que não é a contagem real da CPU) aqui. Portanto, é isso que você está procurando.

Exemplo:

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

Não se esqueça de desligar o serviço do executor como este (ou seu programa não sair):

service.shutdown();

Aqui, apenas um esboço rápido de como configurar um código MT baseado no futuro (offtopic, para ilustração):

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)));
    }

Então você precisa acompanhar quantos resultados você espera e recuperá -los assim:

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

Na aula de tempo de execução, existe um método chamado DisponívelProcessors (). Você pode usar isso para descobrir quantas CPUs você tem. Como o seu programa está vinculado à CPU, você provavelmente gostaria de ter (no máximo) um tópico por CPU disponível.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top