【问题标题】:Wait for ThreadPool to finish and start SingleThread等待 ThreadPool 完成并启动 SingleThread
【发布时间】:2018-04-15 00:38:26
【问题描述】:

我目前正在尝试通过使用 10 个线程的 ThreadPool 和仅检查一个线程的第二次运行来检查一个数字是否为素数。这里的想法是,我还检查了使用 10 个线程和 1 个单线程的 ThreadPool 之间的速度差异。

我的问题是,在启动单线程操作之前,我对如何等待 PoolThread 完成有点困惑。

我尝试在我的 PrimeTask 类中同步一个函数,但我对线程还是很陌生,不知道为什么我没有得到想要的行为。我很想知道我缺少什么以及为什么。

import java.util.concurrent.*;

public class PrimeChecker
{
    private static ExecutorService executor;
    private final static long number = 9223372036854775783L;
    private final static int numberOfThreads = 10;
    private static long startValues;
    private static long endValues;
    static long startTime;
    static long endTime;

    private PrimeChecker() { };

    public static void main(String[] args)
    {
        init();
        runThreads();
    }

    private static void init()
    {
        startValues = 3L;
        endValues = (long) Math.sqrt(number) / 10L;
    }

    private static void runThreads()
    {
        startTime = System.currentTimeMillis();
        executor = Executors.newFixedThreadPool(numberOfThreads);
        System.out.print("Chekcing if " + number + " is a prime number, multithreaded.\n");
        for (int x = 1; x < 10; x++)
        {
            executor.execute(new PrimeTask(number, startValues, endValues));
            startValues = ((endValues / 10) * x);
            endValues = ((endValues / 10) * (x + 1));
        }
        executor.shutdown();

        singlethreadedPrime();
    }

    private static void singlethreadedPrime()
    {
        startTime = System.currentTimeMillis();
        executor = Executors.newFixedThreadPool(1);
        System.out.println("Chekcing if " + number + " is a prime number, singlethreaded.");
        executor.execute(new PrimeTask(number, startValues, endValues));
        executor.shutdown();
    }

    static class PrimeTask implements Runnable
    {
        private long number;
        private long startValue;
        private long endValue;

        public PrimeTask(long Numb, long startVal, long endVal)
        {
            number = Numb;
            startValue = startVal;
            endValue = endVal;
        }


        @Override
        public void run() 
        {
            if (isPrime(number, startValue, endValue))
            {
                endTime = System.currentTimeMillis();
                System.out.printf("Time millisecond: %d\n", (endTime - startTime));
                System.out.println(number + " is Prime");
            }
            else
            {
                endTime = System.currentTimeMillis();
                System.out.printf("Time millisecond: %d\n" + (endTime - startTime));
                System.out.println(number + " not Prime");  
            }
        }

        public static synchronized boolean isPrime(long n, long sV, long eV)
        {
            if((n % 2) == 0)
            {
                return false; // not prime
            }
            else
            {
                for(long i = sV; i*i <= eV; i+=2) 
                {
                    if(n%i==0)
                        return false; // not prime
                }
                return true; // prime
            }
        }
    }
}

【问题讨论】:

  • Executors 的工作量完全相同——我的意思是字面意思。为了让您的代码利用多个线程,您实际上需要执行多个任务(每个任务由单个线程执行)。所以在你的runThreads 方法中,你需要将你的工作量分解成(可能是 10 个)部分,每个部分计算整体的特定范围(即(endValues - startValues) / 10 会给你每个单独任务的整体范围)跨度>
  • 回答您的问题:像往常一样,您只需阅读 javadoc:docs.oracle.com/javase/8/docs/api/java/util/concurrent/…。这是类中列出的第一个方法!

标签: java multithreading threadpool


【解决方案1】:

您使用了“执行”,但您似乎想等待结果。 所以你可以使用 submit() 来返回一个未来。 因此,您可以等待 future.get() (阻塞)。

只有一个未来,这是微不足道的。对于 10 个期货,您会将期货堆积在一个列表中,然后当所有期货都提交后,在每个期货上调用 .get() 相当简单。第一个需要一些时间,但后面的会更快,如果已经完成,甚至不会阻塞 .get() 。 (当然你可以轮询 future.isDone() 但这很浪费)

您使用的 executor.shutdown() 应该等待所有正在进行的任务完成,但问题可能是它们并非都在进行中,而只是排队。

最后,您可以使用 CountDownLatch 等待所有完成。将倒计时锁存器传递给所有任务。

【讨论】:

    猜你喜欢
    • 2010-09-29
    • 1970-01-01
    • 2017-06-13
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多