Methode nach bestimmter Zeit beenden


marc_242

Grünschnabel
Hi,

Meine Problem ist eigentlich ganz simpel: Wie kann man eine Methode aufrufen und sagen "ich geb dir x Sekunden, danach beende, ob du fertig bist oder nicht"?
Hab schon online recherchiert aber ich komm nicht drauf. Hat wohl irgendwas mit dem thread-wait-interrupt-Zeugs zum tun, oder?

Danke
 

soa

Erfahrenes Mitglied
Hallo,

ich denke, dass Du diese Funktioanität auch gut in der Funktion selbst unterbringen könntest.

Mit der Klasse java.util.date holst Du Dir einfach das aktuelle Datum und läßt eine
kopfgesteuerte Schleife solange durchlaufen, bis die von Dir vorgegebene Zeit verstrichen ist.

Schau mal hier : http://java.sun.com/j2se/1.5.0/docs/api/index.html

Viele Grüße
 

marc_242

Grünschnabel
Erstmal danke für die Antwort.
Sowas in der Richtung hab ich mir auch schon gedacht, aber bei mir scheitert's noch an der Implementierung.
 

soa

Erfahrenes Mitglied
gut, man könnte das auch mit einem Interrupt machen.

Nachstehende Funktion läuft für ca. 20 Sekunden.
sleep(1000) entspricht ungefähr einer Sekunde.

PHP:
public void iterate(){
  while ( num < 2000) {

     current.setValue(num);
     try {
       Thread.sleep(1000);
          } catch (InterruptedException e) {  }

           num += 100;
    }
}

Vielleicht hilft es ja.

VG
 

zeja

Erfahrenes Mitglied
Wenn es eine Method ist welche du nicht über eine while-Schleife kontrollieren kannst (weil das ne einigermaßen saubere Lösung ist) gehts auch so:
Java:
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

public class ThreadTest {

	private static boolean stop = false;

	public static void endlessMethod() {
		while (true) {
			System.out.println("endless");
		}
	}

	public static void methodTimeout() {
		final Thread endless = new Thread( ) {

			@Override
			public void run() {
				endlessMethod( );
			}
		};
		endless.start( );

		Timer t = new Timer( );
		t.schedule(new TimerTask( ) {

			@Override
			public void run() {
				endless.stop( );
				stop = true;
			}

		}, TimeUnit.SECONDS.toMillis(5));

		while (!stop) {
			// wait
		}
	}

	public static void main(String[] args) {
		long start = System.currentTimeMillis( );
		methodTimeout( );
		long end = System.currentTimeMillis( );
		System.out.println((end - start) + "ms");
	}

}
 

Thomas Darimont

Premium-User
Hallo,

schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import static java.util.concurrent.TimeUnit.SECONDS;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @author Thomas.Darimont
 * 
 */
public class TimeConstrainedMethodExecutionExample {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception{
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        final int argument = 42;
        int result = -1;
        try {
            result = executorService.submit(new Callable<Integer>(){
                public Integer call() throws Exception {
                    return operation(argument);
                }
            }).get(5,SECONDS);
        } catch (TimeoutException e) {
            //TODO log
            System.out.println("Invocation did not return before timeout...");
        }
        System.out.println(result);
        
        executorService.shutdownNow();
        
    }

    public static int operation(int arg) {
        sleep((int) (Math.random() * 10), SECONDS);
        return arg * arg;
    }

    /**
     * @param timeUnit
     * @param numberOfSeconds
     * 
     */
    private static void sleep(int amount, TimeUnit timeUnit) {
        try {
            timeUnit.sleep(amount);
        } catch (InterruptedException e) {
            //ignore
            //e.printStackTrace();
        }
    }
}
Das kann man dann händisch hinter einem DynamicProxy verstecken oder per AOP über AspectJ / Spring AOP einweben lassen.
So in etwa könnte dann ein dynamic Proxy basierter Ansatz aussehen:
Java:
/**
 * 
 */
package de.tutorials;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @author Thomas.Darimont
 * 
 */
public class TimeConstrainedMethodExecutionExample {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {

		IService service = (IService)Proxy.newProxyInstance(Thread.currentThread()
				.getContextClassLoader(), new Class[] { IService.class },
				new TimeConstraintAwareInvocationHandler(new Service()));
		
		System.out.println(service.operation("aaa"));

	}

	static interface IService {
		@TimeConstrained(amount = 5, timeUnit = TimeUnit.SECONDS)
		String operation(String arg);
	}

	static class Service implements IService {
		public String operation(String arg) {
			
			try {
				TimeUnit.SECONDS.sleep((long)(10 * Math.random()));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			return arg.toUpperCase();
		}
	}

	static class TimeConstraintAwareInvocationHandler implements
			InvocationHandler {

		static ExecutorService executorService = Executors
				.newCachedThreadPool();

		Object invocationTarget;

		public TimeConstraintAwareInvocationHandler(Object invocationTarget) {
			this.invocationTarget = invocationTarget;
		}

		public Object invoke(final Object proxy, final Method method,
				final Object[] args) throws Throwable {
			if (method.isAnnotationPresent(TimeConstrained.class)) {
				TimeConstrained timeConstraind = method
						.getAnnotation(TimeConstrained.class);
				try {
					return executorService.submit(new Callable<Object>() {
						
						public Object call() throws Exception {
							return method.invoke(getInvocationTarget(), args);
						}
						
					}).get(timeConstraind.amount(), timeConstraind.timeUnit());
				} catch (TimeoutException e) {
					// Timeout occured
					// e.printStackTrace();
					return null;
				}
			}
			return method.invoke(getInvocationTarget(), args);
		}

		/**
		 * @return the invocationTarget
		 */
		public Object getInvocationTarget() {
			return invocationTarget;
		}

		/**
		 * @param invocationTarget
		 *            the invocationTarget to set
		 */
		public void setInvocationTarget(Object invocationTarget) {
			this.invocationTarget = invocationTarget;
		}

	}

	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.METHOD)
	static @interface TimeConstrained {
		TimeUnit timeUnit();

		long amount();
	}
}
Gruß Tom