在给定时间过后,在线程中停止算法

时间:2014-09-25 16:16:29

标签: java multithreading

让我们说我有一个针对给定参数做某事的算法。如果算法运行时间超过100毫秒,那么我想停止它并再次尝试使用不同的参数。

我在下面发布了测试随机参数算法的代码......以及我认为代码可能如下所示:

public class StopThread {
    private Lock lock = new ReentrantLock();

    public static void main(String... args) {
        System.out.println("Starting threads...");
        (new StopThread()).startThreads(100);
    }

    private void startThreads(int nrOfThreads) {
        for (int i = 0; i < nrOfThreads; i++) {
            startThread(i, (long) (Math.random() * 10000000000l));
            System.out.println("Started thread number " + (i + 1));
        }
    }

    private void startThread(final int number, final long load) {
        Thread workerThread = new Thread() {
            @Override
            public void run() {
                try {
                    lock.lock();
                    doAlgorithmWork(load);
                } finally {
                    System.out.println("Thread " + (number + 1) + " finished...");
                    lock.unlock();
                }
            }
        };
        Thread timerThread = new Thread() {
            @Override
            public void run() {
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                }
            }
        };

        workerThread.start();
        timerThread.start();

        do {
            if (!workerThread.isAlive() || !timerThread.isAlive()) {
                workerThread.stop();
                timerThread.stop();
            }
        } while (!workerThread.isAlive() && !timerThread.isAlive());
    }

    protected void doAlgorithmWork(long load) {
        while (load-- > 0) {
        }
    }
}

我觉得这个问题应该已经有了答案,但是我发现到现在为止看起来很复杂,而且我不知道如何使用它。我对线程知之甚少,如果你能发布一些代码,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

一个非常简单的解决方案如下:

private void startThreads(int nrOfThreads) {
    for (int i = 0; i < nrOfThreads; i++) {
        Thread worker = new Thread() {
            @Override
            public void run() {
                doAlgorithmWork((long) (Math.random() * 10000000000l));
            }
        }
        worker.start();
        worker.join(100); //block until either the thread is done, or 100ms passed
        if (worker.isAlive()) worker.stop(); //if thread is still alive, stop it
    }
}

这将实现您的目标,但是会遇到许多缺点&#34;

  • 它是单线程的(也就是说,对doAlgorithm的所有调用都是一个接一个地执行,而不是并行执行,因此您只使用机器的单个核心);
  • 它使用了不鼓励的Thread.stop()方法。一种优选的方法是改为停止&#34;停止&#34;标记设置为true(代替stop()调用),并且还会在doAlgorith中不断检查;
  • 它为每个doAlgorithm调用创建一个新线程(而不是重用单个线程),这是浪费&#34;,但对于你的情况可能没什么实际意义

更新:

为了避免弃用的stop()调用,您需要在工作线程中添加一个标志,创建一个单独的类,如下所示:

public class Worker implements Runnable {
    private volatile boolean stopped = false;

    public void stop() {
        stopped = true;
    }

    @Override
    public void run() {
        doAlgorithmWork((long) (Math.random() * 10000000000l));
    }

    private void doAlgorithmWork(long load) {
        while (!stopped && load-- > 0) {
            //calculation
        }
    }
}

然后你的跑步者看起来像这样:

private void startThreads(int nrOfThreads) {
    for (int i = 0; i < nrOfThreads; i++) {
        Thread worker = new Thread(new Worker());
        worker.start();
        worker.join(100); //block until either the thread is done, or 100ms passed
        if (worker.isAlive()) worker.stop(); //if thread is still alive, stop it
    }
}

您还可以为Worker创建一个构造函数,它接受load值(而不是在Worker本身内生成它)。

请注意,如果doAlgorithm()内的计算过于耗时,则线程可能会运行超过100毫秒(因为它总是完成循环中的每个计算)。如果这是一个问题,那么您的替代方法是中断线程(调用worker.interrupt()将导致InterruptedException方法中抛出run()