4

I am embeding Groovy runtime in my code and I would like to have the ability to interrupt it. I don't have control of the scripts that are going to run. I read about groovy.transform.ThreadInterrupt to handle thread interruptions but for some reason this code below isn't working as intended. It's actually waiting 10000 ms instead of the 1000 where it should get interrupted.

Any ideas? Thank you.

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.transform.ThreadInterrupt;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;

public class GroovyTest extends Thread {
    private Binding binding;
    private GroovyShell shell;

    public GroovyTest() {
        CompilerConfiguration compilerConfig = new CompilerConfiguration();
        compilerConfig.addCompilationCustomizers(
                new ASTTransformationCustomizer(ThreadInterrupt.class));

        binding = new Binding();

        shell = new GroovyShell(this.getClass().getClassLoader(), binding, compilerConfig);
    }

    @Override
    public void run() {
        System.out.println("Started");

        shell.run("for(int i = 0; i < 10; i++) {sleep(1000)}", "test", new String[] {});

        System.out.println("Finished");
    }

    public static void main(String args[]) throws InterruptedException {
        GroovyTest test = new GroovyTest();

        test.start();

        System.out.println("Sleeping: " + System.currentTimeMillis());

        Thread.sleep(1000);

        System.out.println("Interrupting: " + System.currentTimeMillis());

        test.interrupt();
        test.join();

        System.out.println("Interrupted?: " + System.currentTimeMillis());
    }
}
4

1 回答 1

4

回答我自己的问题。即使没有闭包,Groovy 的静态方法 sleep 也不会中断。如果你问我,这是很奇怪的默认值。推荐的方法是调用 Thread.sleep(ms)

private static void sleepImpl(long millis, Closure closure) {
    long start = System.currentTimeMillis();
    long rest = millis;
    long current;
    while (rest > 0) {
        try {
            Thread.sleep(rest);
            rest = 0;
        } catch (InterruptedException e) {
            if (closure != null) {
                if (DefaultTypeTransformation.castToBoolean(closure.call(e))) {
                    return;
                }
            }
            current = System.currentTimeMillis(); // compensate for closure's time
            rest = millis + start - current;
        }
    }
}
于 2011-08-13T16:55:30.530 回答