ReentrantLock.tryLock () не блокируется - PullRequest
3 голосов
/ 12 января 2012

Я думаю, что я просто не вижу что-то, поскольку я заставил это работать в прошлом.

Моя блокировка не удерживает эксклюзивную блокировку, и когда создается новый экземпляр объекта,tryLock возвращает значение true, и запланировано еще TimerTask.

public class A {
    private static Timer timer = new Timer();
    private static Lock clean_lock = new ReentrantLock();
    private static ConcurrentHashMap<String,B> _b_dict = new ConcurrentHashmap<String,B>();

    public A() {
        if(clean_lock.tryLock()) {
            timer.scheduleAtFixedRate(new TimerTaskThread(), new Date(), 60000);
        }
    }

    //Various NON static methods 
    // use an iterator at one point so they must be NON static

    class TimerTaskThread extends TimerTask {
        public void run() {
            //delete old stuff in _b_dict
        }
    }
}

//sample usage
public class Main {
    public Main() {
        A a = new A();
        a.contains(new B());
    }
}

Ответы [ 3 ]

10 голосов
/ 12 января 2012

Вы создаете другой экземпляр A из другого потока? Потому что, если вы создаете оба экземпляра из одного и того же потока, блокировка, которая возвращается, tryLock, очевидно, возвращает true.

Если вы действительно хотите планировать из конструктора, а не из статического блока, вы должны использовать статическую переменную AtomicBoolean и планировать таймер только в том случае, если compareAndSet(false, true) возвращает true.

3 голосов
/ 12 января 2012

С какой целью вы используете замок здесь;просто чтобы гарантировать, что timer.scheduleAtFixedRate вызывается только один раз (при первом вызове конструктора A)?

Вместо этого вы можете сделать это в статическом инициализаторе, так что вам не нужноБлокировка вообще:

public class A {
    private static final Timer timer = new Timer();
    private static final ConcurrentHashMap<String,B> _b_dict = new ConcurrentHashmap<String,B>();

    static {
        timer.scheduleAtFixedRate(new TimerTaskThread(), new Date(), 60000);
    }

    // etc.
}

Если вы используете статический блок, планирование будет выполняться при инициализации класса (после его загрузки), а не при первом создании его экземпляра.

Другой возможностью является использование AtomicBoolean:

public class A {
    private static final Timer timer = new Timer();
    private static final AtomicBoolean initDone = new AtomicBoolean();
    private static final ConcurrentHashMap<String,B> _b_dict = new ConcurrentHashmap<String,B>();

    public A() {
        if (!initDone.getAndSet(true)) {
            timer.scheduleAtFixedRate(new TimerTaskThread(), new Date(), 60000);
        }
    }

    // etc.
}
1 голос
/ 12 января 2012

Я бы так написал.

public class A {
    private static final ExecutorService service = Executors.newScheduledExecutorService();
    private static final ConcurrentMap<String,B> _b_dict = new ConcurrentHashmap<String,B>();
    static {
       service.scheduleAtFixedRate(new Runnable() {
           public void run() {
               cleanUp();
           }
       }, 1, 1, TimeUnit.MINUTES);
    }

    static void cleanUp() {
       // remove old entries
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...