【问题标题】:Java parallel tasks , only executing onceJava并行任务,只执行一次
【发布时间】:2018-07-17 13:22:30
【问题描述】:

我的这段代码没有并行执行任务, 在这种情况下它只执行一次代码(无论是在 for 循环中,但它应该是 2):

public class mqDirect {
    public static void main(String args[]) throws Exception {
        int parallelism = 2;
        ExecutorService executorService =
                Executors.newFixedThreadPool(parallelism);
        Semaphore semaphore = new Semaphore(parallelism);
        for (int i = 0; i < 1; i++) {
            try {
                semaphore.acquire();
                // snip ... do stuff.. 
                semaphore.release();
            } catch (Throwable throwable) {
                semaphore.release();
            }

            executorService.shutdownNow();
        }
    }
}

【问题讨论】:

  • 抱歉,我不让我发布代码,尽管尝试格式化它..
  • 您可以将代码发布为文本,其他人也许可以将其编辑成形状。
  • 您的示例创建了一个从未使用过的ExectorService 实例。为什么?

标签: java multithreading parallel-processing


【解决方案1】:

在 Java 中,使代码并行工作的主要方法是创建一个 Thread,并将新的 Runnable 作为构造函数参数。然后你需要start它。

有很多教程可以帮助您正确实现这一点。

就您的代码而言,您只是创建一个ExecutorService(而不是使用它),创建一个Semaphore(应该在thread 中完成,但不是),执行一些过程然后关闭Executor

顺便说一句:ShutDownNow 可能不是你想要的,你应该使用ShutDown

【讨论】:

  • Re "...创建一个Thread ...然后您需要启动它或使用Executor。" IMO,这令人困惑。您似乎建议通过创建一个新的Thread 实例来解决问题,然后使用Executor 对新的Thread 做一些事情。这是没有意义的。您可能打算建议使用Executor 而不是 使用Thread,但我认为对于不熟悉线程池 概念。
【解决方案2】:

好的,所以我找到了这个很好的教程 http://programmingexamples.wikidot.com/threadpoolexecutor

我做过类似的事情

public class mqDirect {
int poolSize = 2;

int maxPoolSize = 2;

long keepAliveTime = 10;

ThreadPoolExecutor threadPool = null;

final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(
        5);

public mqDirect()
{
    threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize,
            keepAliveTime, TimeUnit.SECONDS, queue);

}

public void runTask(Runnable task)
{

    threadPool.execute(task);

    System.out.println("Task count.." + queue.size());

}

public void shutDown()
{
    threadPool.shutdown();
}





public static void main (String args[]) throws Exception
{

    mqDirect mtpe = new mqDirect();
    // start first one
    mtpe.runTask(new Runnable()
    {
        public void run()
        {
            for (int i = 0; i < 2; i++)
            {
                try
                {
                    System.out.println("First Task");
                    runMqTests();
                    Thread.sleep(1000);
                } catch (InterruptedException ie)
                {
                }
            }
        }
    });
    // start second one
    /*
     * try{ Thread.sleep(500); }catch(InterruptedException
     * ie){}
     */
    mtpe.runTask(new Runnable()
    {
        public void run()
        {
            for (int i = 0; i < 2; i++)
            {
                try
                {
                    System.out.println("Second Task");
                    runMqTests();
                    Thread.sleep(1000);
                } catch (InterruptedException ie)
                {
                }
            }
        }
    });
    mtpe.shutDown();

   // runMqTests();

}

而且它有效! 但问题是,这个重复的代码... runMqtests() 是同一个任务,有没有办法指定它在不重复代码的情况下并行运行?

我基于此的示例假设每个任务都不同。

【讨论】:

    【解决方案3】:

    我的这段代码不是并行执行任务,它只执行这种情况下的代码一次(无论在for循环中是什么,但它应该是2):

    仅仅因为您实例化了一个ExecutorService 实例并不意味着事情会神奇地并行运行。除了将其关闭之外,您实际上还需要使用该对象。

    如果您希望循环中的内容在服务的线程中运行,那么您需要执行以下操作:

    int parallelism = 2;
    ExecutorService executorService = Executors.newFixedThreadPool(parallelism);
    for (int i = 0; i < parallelism; i++) {
        executorService.submit(() -> {
            // the code you want to be run by the threads in the exector-service
            // ...
        });
    }
    // once you have submitted all of the jobs, you can shut it down
    executorService.shutdown(); 
    // you might want to call executorService.awaitTermination(...) here
    

    请务必注意,这将在服务中运行您的代码,但不能保证它将“并行”运行。这取决于您的处理器数量和线程固有的竞争条件。例如,第一个任务可能在第二个任务开始之前启动、运行并完成其代码。这就是设计为异步的线程程序的本质。

    但是,如果您至少有 2 个内核,并且您提交以供 executor-service 运行的代码需要很长时间才能运行,那么它们很可能会在某个时间点同时运行。

    最后,正如@OldCurmudgeon 指出的那样,您应该在服务上调用shutdown(),它允许当前已提交到服务的作业运行,而不是shutdownNow(),后者取消和排队作业,并且还调用thread.interrupt() 在任何运行作业。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-13
      • 1970-01-01
      相关资源
      最近更新 更多