如何锁定java方法以保护多个调用

时间:2010-03-11 22:15:39

标签: java concurrency

我有一个应用程序,每15分钟左右从远程数据库复制一次。它只是使两个存储库保持同步。一旦进行此复制,就不可能再次执行此操作。我已经设置了以下结构,但我不确定它是否是正确的方法。

public class ReplicatorRunner {

       private static Lock lock = new ReentrantLock();

       public replicate() {

           if (lock.tryLock()) {
               try {
                   // long running process
               } catch (Exception e) {                   
               } finally {
                   lock.unlock();
               }               
           } else {
               throw new IllegalStateException("already replicating");
           }

       }

}

public class ReplicatorRunnerInvocator {

    public void someMethod() {

        try {
            ReplicatorRunner replicator = new ReplicatorRunner();
            replicator.replicate();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }

    }

}

ReplicatorRunner是拥有方法replicate的类,一次只能运行一个。

编辑。 如果方法已在任何实例上运行,我需要下一次失败调用( not block )。

5 个答案:

答案 0 :(得分:4)

这看起来不错。 ReentrantLock.tryLock()只会将锁定给一个线程,因此不需要synchronized。它还可以防止您所说的同步中固有的阻塞。 ReentrantLock是Serializable,因此应该在整个群集中工作。

去吧。

答案 1 :(得分:1)

public replicate()更改为public synchronized replicate()

这种方式复制只允许一次访问一个线程。您还可以删除ReentrantLock和所有相关代码。

答案 2 :(得分:1)

我最终使用了以下内容:

public class ReplicatorRunner {

       private static Semaphore lock = new Semaphore(1);

       public replicate() {

           if (lock.tryAcquire()) {
               try {                              
                   // basic setup                  
                   Thread t = new Thread(new Runnable() {
                       public void run() {
                           try {
                               // long running process                               
                           } catch Exception (e) {
                               // handle the exceptions
                           } finally {
                               lock.release();
                           }
                       }
                   })
                   t.start();

               } catch (Exception e) {
                   // in case something goes wrong
                   // before the thread starts
                   lock.release();
               }              
           } else {
               throw new IllegalStateException("already replicating");
           }

       }

}

public class ReplicatorRunnerInvocator {

    public void someMethod() {

        try {
            ReplicatorRunner replicator = new ReplicatorRunner();
            replicator.replicate();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }

    }

}

答案 3 :(得分:0)

查看信号量类here或将方法标记为已同步  在任何给定时间执行该方法的线程都拥有对它的锁定,从而避免其他线程调用该方法,直到其执行结束。
编辑:如果您希望其他线程失败,您可以使用Lock,并测试是否可以通过tryLock方法获得锁定。

答案 4 :(得分:0)

在不查看ReentrantLock的细节的情况下,我发现这种多个同时复制例程的防止将仅限于单个JVM实例。

如果该类的另一个实例在单独的JVM中启动,那么您可能遇到了麻烦。

为什么不在数据库上放置锁机制?即控制表中的一行,设置为描述复制是否正在运行的值,并在复制完成时重置该值。