1

リソース(リンクリストとしましょう)が2つのサービス間で共有されるという単純な要件があります.1つはそれに要素を追加し、もう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は概念的に単純で、正しく理解するのが簡単であるため、タイムアウト (または のその他の機能ReentrantLock) が必要でない限り、 の使用のみを検討することをお勧めしますsynchronized

于 2016-02-07T13:50:16.007 に答える