【问题标题】:Time out a java code?java代码超时?
【发布时间】:2014-06-18 09:12:32
【问题描述】:

我正在编写一个在线 java 编程应用程序,我将 java 代码作为用户的输入,并通过 python 脚本编译和执行后返回输出。

为了控制内存堆,我有一个在 JVM 中运行代码时使用 -Xms 和 -Xmx 的标准解决方案。我已经安装了 Sun Java 1.7.0_40。

现在的问题是我对如何使用时间限制来限制代码感到困惑。例如,用户在我的应用中提交的任何代码都不应运行超过 T 秒,其中 T 是一个变量。

我使用 Timer 类编写了一个简单的 hack,但问题是我必须使用大量正则表达式将其注入到我主要想避免的用户代码中。作为一名程序员,由于我在 python 和 c++ 方面比 java 更自在,因此我需要一些指导,了解是否存在一些简单的解决方案来解决此类问题,或者使用 Timer 类的优缺点是什么。

任何帮助将不胜感激! 谢谢

【问题讨论】:

  • 我正在使用 Python 2.7,然后我通过子进程尝试了 sleep 和 kill 方法来超时,但这不是我想要的。当他的代码的实际执行时间小于 T 秒时,我不希望用户等待 T 秒。

标签: java timeout online-compilation


【解决方案1】:

我已经使用 ExecutorService 完成了简单的“TimeoutThread”实用程序。

2 类:

package eu.wordnice.thread;
/*** Runa.java ***/

import java.util.concurrent.Callable;

public class Runa implements Callable<Object> {

    private Runnable run = null;

    public Runa(Runnable run) {
        this.run = run;
    }

    public Runa(Thread run) {
        this.run = run;
    }

    public Runa() {}

    public Object call() throws Exception {
        if(run != null) {
            run.run();
        }
        return -1;
    };

}

还有:

package eu.wordnice.thread;
/*** TimeoutThread.java ***/
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class TimeoutThread {

    public Runa run = null;
    public ExecutorService executor = null;
    public long timeout = 100L;
    private boolean canceled = false;
    private boolean runed = false;

    public TimeoutThread(Runnable runit, long timeout) {
        this(new Runa(runit), timeout);
    }

    public TimeoutThread(Runa runit, long timeout) {
        this.run = runit;
        if(timeout < 1L) {
            timeout = 10L;
        }
        this.timeout = timeout;
    }


    public Object run() {
        return this.run(false);
    }

    public Object run(Object defaulte) {

        this.runed = true;
        List<Future<Object>> list = null;
        try {
            this.executor = Executors.newCachedThreadPool();
            list = executor.invokeAll(Arrays.asList(this.run), this.timeout, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            e.printStackTrace();
            this.canceled = true;
        }
        executor.shutdown();

        if(list == null) {
            return defaulte;
        }
        if(list.size() != 1) {
            return defaulte;
        }

        try {
            Future<Object> f = list.get(0);
            try {
                return f.get();
            } catch (Exception e) {
                this.canceled = true;
            }
        } catch (Exception e) { }
        return defaulte;
    }

    public boolean wasRunned() {
        return this.runed;
    }

    public boolean wasCanceled() {
        return this.canceled;
    }

}

示例:

public static void main(String... blah) {
        TimeoutThread thr = new TimeoutThread(new Runa() {

            @Override
            public Object call() throws Exception {
                while(true) {
                    System.out.println("Yeeee");
                    Thread.sleep(300L);
                }
            }



        }, 500L);
        thr.run();
    }

打印:

Yeeee
Yeeee

编辑!

抱歉,这是 Timeout Runnable。如果您想要 Timeout Tread,只需将代码/调用放入 Thread。

public static void main(String... blah) {
        final TimeoutThread thr = new TimeoutThread(new Runa() {

            @Override
            public Object call() throws Exception {
                while(true) {
                    System.out.println("Yeeee");
                    Thread.sleep(300L);
                }
            }



        }, 500L);

        new Thread() {
            @Override
            public void run() {
                thr.run(); //Call it
            }
        }.start(); //Run it
    }

【讨论】:

    【解决方案2】:

    我会看看在 Java 中为此使用 ExecutorService 并让具有您想要超时的功能的类实现可运行 - 因此使用 Java 的线程功能来帮助您。

    您应该能够使用以下代码使线程超时:

    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.MINUTES); // Timeout of 10 minutes.
    executor.shutdown();
    

    但您可能需要稍微查看一下文档才能使其适用于您的用例。

    有关此类事情的更多建议,请参阅以下post

    不确定您是否希望在 Python 代码或 Java 中设置超时,但希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      你可以使用ThreadPoolExecutor

      样本:

      int  corePoolSize  =    5;
      int  maxPoolSize   =   10; 
      long keepAliveTime = 5000;
      
      ExecutorService threadPoolExecutor =
          new ThreadPoolExecutor(
                  corePoolSize,
                  maxPoolSize,
                  keepAliveTime,
                  TimeUnit.MILLISECONDS,
                  new LinkedBlockingQueue<Runnable>()
                  );
      threadPoolExecutor.execute(new Runnable(){ 
      
          @Override
          public void run() {
             // execution statements
          });
      

      参考文献

      1. http://tutorials.jenkov.com/java-util-concurrent/threadpoolexecutor.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-08
        • 2017-11-17
        • 2023-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多