有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

假设我有一个算法,对给定的参数做一些事情。如果该算法运行时间超过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) 个答案

  1. # 1 楼答案

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

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

    这将实现您的目标,但存在许多“缺点”

    • 它是单线程的(也就是说,对doAlgorithm的所有调用都是一个接一个地执行,而不是并行执行,因此您只使用机器的单个内核)
    • 它使用不推荐的Thread.stop()方法。首选的方法是将“stop”标志设置为true(代替stop()调用),并且在doAlgorith中不断检查该标志
    • 它为每个doAlgorithm调用创建一个新线程(而不是重用一个线程),这是“浪费”,但对于您的情况来说可能没有什么实际意义

    更新:

    为了避免不推荐的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()将导致在run()方法中抛出InterruptedException