1

我有一个简单的要求,其中一个资源(比如说一个链表)在两个服务之间共享:一个向它添加元素,另一个计算它的统计信息。我想在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();
    }

 }

唯一强制性的事情是不应该错过任何调用(加法器或计算器)。

4

1 回答 1

1

你有使用可重入锁的特定理由吗?你的calculateStatistics()方法做 IO 吗?(不确定您的示例是否过于简化)

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

于 2016-02-07T13:50:16.007 回答