Reputation: 1319
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 ?
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
Reputation: 10323
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
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
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