使用java中的重入锁定限制对共享数据的访问

时间:2016-02-07 13:39:01

标签: java reentrantlock

我有一个简单的要求,即在两个服务之间共享一个资源(让我们说一个链表):一个向其添加元素,另一个计算它的统计信息。我想在java中使用重入锁。我想出了以下解决方案。

有没有比这更好的解决方案?

public class SharedServer {
    private List<Integer> numbers;

    public SharedServer(List<Integer> numbers){
        this.numbers = numbers;
    }

    Lock lock = new ReentrantLock();

    public void addElements(int element){
        try{
            Thread.sleep(100);
            System.out.println("Adding element");
            numbers.add(element);
            System.out.println("Added : "+element);
        }catch(InterruptedException e){
            System.out.println("Interrupted while adding elements");
        }  
    }

    public void caluclateStatistics(){
        try{
            Thread.sleep(200);
            System.out.println("calculating statistics");
            System.out.println("Min : "+Collections.min(numbers)+" Max :      "+Collections.max(numbers)+" Avg : "+(Collections.min(numbers)+Collections.max(numbers))/numbers.size());
        }catch(InterruptedException e){
            System.out.println("Interrupted while performing calculations on elements");
        }
   }

}

public class StatisticsCalculator implements Runnable {

    private SharedServer sharedServer;

    public StatisticsCalculator(SharedServer sharedServer){
        this.sharedServer = sharedServer;
    }

    @Override
    public void run() {
        System.out.println("Calculator");
        boolean acquired = false;
        try {
            acquired = sharedServer.lock.tryLock(300,TimeUnit.MILLISECONDS);
            sharedServer.caluclateStatistics();
        } catch (InterruptedException e) {
            System.out.println("COULD NOT ACQUIRE CALCULATOR");
            e.printStackTrace();
        }finally{
            if(acquired){
                sharedServer.lock.unlock();
                System.out.println("Calculator released");
            }
        }

  }
}


public class ElementAdder implements Runnable {

    private SharedServer sharedServer;

    public ElementAdder(SharedServer sharedServer){
        this.sharedServer = sharedServer;
    }

    @Override
    public void run() {
        System.out.println("Adder");
        boolean acquired = false;
        try {
            acquired = sharedServer.lock.tryLock(300,TimeUnit.MILLISECONDS);
            sharedServer.addElements(ThreadLocalRandom.current().nextInt(1, 1000));
        } catch (InterruptedException e) {
            System.out.println("COULD NOT ACQUIRE ADDER");
            e.printStackTrace();
        }finally{
            if(acquired){
                sharedServer.lock.unlock();
                System.out.println("Adder released");
            }
        }
     }

}


public class Main {

    public static void main(String[] args) {
        List<Integer> ints = new ArrayList<>();
        SharedServer sharedService = new SharedServer(ints);
        ExecutorService executorService1 = Executors.newCachedThreadPool();
        ExecutorService executorService2 = Executors.newCachedThreadPool();
        for(int index=0; index<50;index++){
            executorService1.submit(new ElementAdder(sharedService));
        }
        for(int index=0; index<50;index++){
            executorService2.submit(new StatisticsCalculator(sharedService));
        }
        executorService1.shutdown();
        executorService2.shutdown();
    }

 }

只有强制性的事情是不应该错过任何电话(加法器或计算器)。

1 个答案:

答案 0 :(得分:1)

您是否有特定理由使用折返锁定?您的calculateStatistics()方法是否执行IO? (不确定你的例子是否过于简化)

通常,synchronized在概念上更简单,更容易正确,因此除非您需要超时(或ReentrantLock的其他功能),否则您可能只想使用synchronized