-2

I'm developing the cache of images in a disk in java. One of requests to cache is TimeToLive parameter. I really dont know, how to do it, that is why I'm asking to you.

As I understand, some independent of main thread method shold check every object in cache for TTL parameter. If the value is over, then object should be deleted. Checking one time a minute, for example.

Adey
  • 1,846
  • 1
  • 10
  • 18
  • 1
    What *exactly* you don't understand? Your overall description suggests that you understand your requement on a technical level, so what's the problem then? – M. Prokhorov Feb 02 '18 at 11:27
  • How are your images stored in the cache? as individual files? – Maurice Perry Feb 02 '18 at 11:29
  • @M. Prokhorov I need a java class that allows to do some actions in a certain period of time (for example checking ttl) – Adey Feb 02 '18 at 11:46
  • @Maurice Perry, yes – Adey Feb 02 '18 at 11:46
  • 1
    @Adey, you should have said so from the start. There is a `ScheduledExecutorService` interface, which is a general building block for timed task checking. You can create instances of it by calling respective methods on `java.util.concurrent.Executors` class, or by creating an instance of `java.util.concurrent.ScheduledThreadPoolExecutor`. Class (I advise you to use interface as variable type though, that'll make your code much easier to test. – M. Prokhorov Feb 02 '18 at 13:04

1 Answers1

1

Assuming your cache is a directory with images in it, you can purge the cache like so:

private static void purge(File dir, long ttl) {
    long minTime = System.currentTimeMillis()-ttl;
    for (File file: dir.listFiles()) {
        if (file.lastModified() < minTime) {
            file.delete();
        }
    }
}

Now if you want to do this periodically, you need a timer:

private static final Timer TIMER = new Timer();

you can then schedule a task for purging:

    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            purge(dir, ttl);
        }
    };
    TIMER.schedule(task, period, period);

The task should be cancelled when not needed anymore.

You can put it all together in a class:

public class Cache implements Closeable {
    private static final Timer TIMER = new Timer(true);

    private final File dir;
    private final long ttl;
    private final TimerTask task;

    public Cache(File dir, long ttl, long purgePeriod) {
        this.dir = dir;
        this.ttl = ttl;
        task = new TimerTask() {
            @Override
            public void run() {
                purge();
            }
        };
        TIMER.schedule(task, purgePeriod, purgePeriod);
    }

    @Override
    public void close() throws IOException {
        task.cancel();
    }

    public synchronized void purge() {
        long minTime = System.currentTimeMillis()-ttl;
        for (File file: dir.listFiles()) {
            if (file.isFile() && file.lastModified() < minTime) {
                file.delete();
            }
        }
    }
}
Maurice Perry
  • 9,261
  • 2
  • 12
  • 24
  • I didn't know how to start. Timer and TimerTask classes is what i needed. Thank you very much! – Adey Feb 02 '18 at 12:16
  • @Adey, please don't use Timer. It's not deprecated probably because it produces too many warnings in old apps. Use `ScheduledExecutorService` instead. – M. Prokhorov Feb 02 '18 at 12:57
  • @M. Prokhorov, agree with you, ScheduledExecutorService is more convenient! Spasibo! – Adey Feb 05 '18 at 14:12
  • @Adey It's more recent, not more convenient. – Maurice Perry Feb 05 '18 at 14:15
  • @Maurice Perry, why not more convenient? As I understand I can't control threads in Timer variant, is it? – Adey Feb 05 '18 at 14:19
  • @Adey that's right: The timer is simpler to use, and the `ScheduledExecutorService` has more features that you probably will not need. That said, I agree that using more recent features is often a safer bet. So, by all means, do use a `ScheduledExecutorService`. – Maurice Perry Feb 05 '18 at 14:23
  • @MauricePerry, so, the next step will be understanding threads works. ty again for your explanations – Adey Feb 05 '18 at 14:32
  • 1
    @MauricePerry, it is more convenient though. It doesn't force you to subclass a TimerTask, so you can implement tasks with lambdas. Because Executor can use several threads, it has better support for long-running tasks. It makes testing the code easier, because `Timer` always starts a new thread, which complicates test result collecting. – M. Prokhorov Feb 05 '18 at 16:26
  • @M.Prokhorov yes: as I said, the timer is much simpler – Maurice Perry Feb 06 '18 at 05:45
  • @M.Prokhorov, by the way, if you are well understanding threads, could not you explain me one moment? I'm trying to make async method with `CompletableFuture`. When initializing `completableFuture = CompletableFuture.supplyAsync(() -> myMethod(), executor)` , I can write executor as a second parameter, or not. If I won't write, what's wrong can happen? – Adey Feb 06 '18 at 09:15
  • @Adey, not much, actually. What'll happen is it'll use a common system thread pool. The side effect of overusing the common pool is overflooding it with tasks, and potentially deadlocking it if tasks require results of other tasks to procceed, but this is true of any thread pool, not just the common one. – M. Prokhorov Feb 06 '18 at 11:18