Тайм-аут Java-код?
Я пишу онлайн-приложение для программирования Java, где я принимаю код Java в качестве ввода от пользователя и возвращает результаты после компиляции и выполнения через скрипт Python.
Для управления кучей памяти у меня есть стандартное решение использования -Xms и -Xmx при запуске кода в JVM. Я установил Sun Java 1.7.0_40.
Теперь проблема в том, что я запутался в том, как ограничить код ограничением по времени. Например, любой код, представленный пользователем в моем приложении, не должен выполняться дольше T секунд, где T - переменная.
Я написал один простой хак с использованием класса Timer, но проблема в том, что мне нужно использовать много регулярных выражений для внедрения его в код пользователя, которого я в первую очередь хочу избежать. Так как я более удобен в программировании на Python и C++, чем на Java, мне нужно несколько советов о том, существует ли какое-то простое решение для такой проблемы или каковы преимущества и недостатки использования класса Timer.
Любая помощь будет высоко ценится! Спасибо
3 ответа
Я сделал простой утилитой TimeoutThread, используя ExecutorService.
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
}
Я хотел бы взглянуть на использование ExecutorService в Java для этого и получить класс с функциональностью, для которой вы хотите использовать тайм-аут, работоспособный, поэтому используйте возможности потоков Java, чтобы помочь вам.
Вы должны быть в состоянии тайм-аут потока, используя следующий код:
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.MINUTES); // Timeout of 10 minutes.
executor.shutdown();
Но вам, возможно, придется немного проверить документацию, чтобы заставить ее работать в вашем случае использования.
Смотрите следующий пост для получения дополнительных советов по этому вопросу.
Не уверен, хотите ли вы установить тайм-аут в своем коде Python или в Java, но, надеюсь, это немного поможет.
Ты можешь использовать 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
});