Adrien Gorrell
Adrien Gorrell

Reputation: 1319

Specify the timeout of a java object

I would like to create an object that dies when its timeout is reached. How can I achieve this ?

For instance in pseudo code:

MyObject O = new MyObject(3000) ; // object created will be null after 3 seconds
wait(4000) ;
if (O == null)
  print("success") ;

Is it possible ?

Edit :

Actually I'm using a large map of MyObjects. Each one should die after 1 min of its creation. Now I am thinking about adding a creationDate to MyObject and a method that would check my map of MyObject when its size becomes too large... and put null to the timeout objects references. That would be another approach considering the fact I don't need all objects to be null as soon as they should (ie, they should be null after 1 min but it's not so important as long as my map isn't huge).

Upvotes: 0

Views: 2078

Answers (3)

kuporific
kuporific

Reputation: 10323

Edit

Perhaps what would fit your needs the best is a cache. Consider Guava's Cache. A Cache can have a limited size (removing LRU elements as necessary), expire elements after a certain time, etc.

An example from their docs:

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
       .maximumSize(1000)
       .expireAfterWrite(10, TimeUnit.MINUTES)
       .removalListener(MY_LISTENER)
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) throws AnyException {
               return createExpensiveGraph(key);
             }
           });

You could implement your own class similar to Java's Reference implementations.

For example:

import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

public class TimeoutReference<T> {
    public final AtomicReference<T> reference;

    /**
     * Create new instance
     * @param referent The reference
     * @param timeout minimum length of time the reference is guaranteed to not
     * be {@code null}.
     * @param unit the units of {@code timeout}
     * @throws NullPointerException if any parameter is {@code null}.
     */
    public TimeoutReference(T reference, long timeout, TimeUnit unit) {
        this.reference = new AtomicReference<>(
                Objects.requireNonNull(reference));
        ScheduledExecutorService service
                = Executors.newSingleThreadScheduledExecutor();
        service.schedule(() -> {
                    this.referent.set(null);
                    service.shutdown();
                }, timeout, unit);
    }

    /**
     * Returns the reference or {@code null} if the time has expired.
     */
    public T get() { // perhaps throw a checked exception for clarity.
        return reference.get();
    }
}

Which seems to work reasonably well,

public static void main(String[] args) throws InterruptedException {
    // object created will be null after 3 seconds
    TimeoutReference<String> o = new TimeoutReference<>(
            "My non-null value", 3, TimeUnit.SECONDS);

    System.out.println("Before: " + o.get());
    Thread.sleep(4000) ;
    System.out.println("After: " + o.get());
}

Which outputs:

Before: My non-null value
After: null

I would caution that a programming style where null as a correct use-case can be error prone.

Upvotes: 1

Andremoniy
Andremoniy

Reputation: 34900

You should create ExecutorService and submit there new Runnable task. It will return you an instance of Future, on which you could do wating for needed time.

    Runnable task = new Runnable {
        @Override
        public void run() {
           // do your job
           // or just:
           MyObject O = new MyObject(3000);
           // some job on O object
        }
    };
    Future<?> future = Executors.newSingleThreadExecutor().submit(task);
    try {
        return future.get(TIMEOUT, TimeUnit.SECONDS);
    } catch (Throwable e) {
        log.error(e.getMessage(), e);            
    }

Upvotes: 1

DirkyJerky
DirkyJerky

Reputation: 1168

If you want to 'kill' an object at a certain point in a program, you can just assign the variable to null and the garbage collection will do it automatically.

// Make MyObject
MyObject O = new MyObject(3000);
// Wait 4 seconds
wait(4000);
// 'delete' it, the object made with `new MyObject(4000)` cannot be used anymore.
O = null;

Upvotes: 1

Related Questions