0

I need to check the presence of a smartcard in my Java application to generate something like an "event" on smartcard removal.

I have a simple method to test it:

public boolean isCardIn(){};

What is the best way to poll this? In this case, should I use a java.utils.Timer.Timer() or an ExecutorService()?


This my current implementation:

To start polling

checkTimer.schedule(new CheckCard(), delay,delay);

And this is the timer's execution:

private class CheckCard extends TimerTask{   

    @Override
    public void run() {
        try{
            if(!SmartcardApi.isCardIn(slot)){
                 // fire event
            }
        }catch(Exception e){
        }
    }

}
Mike
  • 522
  • 2
  • 14
Tobia
  • 9,165
  • 28
  • 114
  • 219

1 Answers1

0

I'd take a look on StackOverflow some more because I think your question's been answered: Java Timer vs ExecutorService?

I think generally, it's better to use newer API, which in this case is the ExecutorService. Here's how I'd do it:

Main method

public static void main(String[] args) throws InterruptedException, ExecutionException {
    ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
    SmartCardApi smartCardApi = new SmartCardApi();

    // Polling job.
    Runnable job = new Runnable() {
        @Override
        public void run() {
            System.out.println("Is card in slot? " + smartCardApi.isCardInSlot());
        }
    };
    
    // Schedule the check every second.
    scheduledExecutor.scheduleAtFixedRate(job, 1000, 1000, TimeUnit.MILLISECONDS);
    
    // After 3.5 seconds, insert the card using the API.
    Thread.sleep(3500);
    smartCardApi.insert(1);
    
    // After 4 seconds, eject the card using the API.
    Thread.sleep(4000);
    smartCardApi.eject();

    // Shutdown polling job.
    scheduledExecutor.shutdown();
    
    // Verify card status.
    System.out.println("Program is exiting. Is card still in slot? " + smartCardApi.isCardInSlot());
}

SmartCardApi

package test;

import java.util.concurrent.atomic.AtomicBoolean;

public class SmartCardApi {
    private AtomicBoolean inSlot = new AtomicBoolean(false);
    
    public boolean isCardInSlot() {
        return inSlot.get();
    }
    
    public void insert(int slot) {
        System.out.println("Inserted into " + slot);
        inSlot.set(true);
    }

    public void eject() {
        System.out.println("Ejected card.");
        inSlot.set(false);
    }
}

Program Output

Is card in slot? false
Is card in slot? false
Is card in slot? false
Inserted into 1
Is card in slot? true
Is card in slot? true
Is card in slot? true
Is card in slot? true
Ejected card.
Program is exiting. Is card still in slot? false

In this case, I'm using a simple Runnable which could call another object in order to fire its event. You could also use a FutureTask instead of this Runnable, but that's just based on your preference for how you want this event to fired..

Community
  • 1
  • 1
Mike
  • 522
  • 2
  • 14
  • I want to focus my question on polling. – Tobia Dec 06 '15 at 11:43
  • I've changed my answer to show how you'd use it. As for the why, the `ExecutorService` is a newer API. I read that there can be issues with `TimerTask`s and its execution time in relation to your system clock, but I've never used either of them personally. The code snippet above is just _one_ way you could use the `ExecutorService` IMO. – Mike Dec 06 '15 at 12:58