I have a simple requirement where a resource (let's say a linked-list) is shared between two services:one adds elements to it and another one calculates statistics of it. I want to use re-entrant locks in java. I have come up with following solution.
Is there any better solution than this?
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();
}
}
Only mandatory thing is no call (adder or calculator) should not miss.