【发布时间】:2016-02-07 13:39:01
【问题描述】:
我有一个简单的要求,其中一个资源(比如说一个链表)在两个服务之间共享:一个向它添加元素,另一个计算它的统计信息。我想在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();
}
}
唯一强制性的就是不调用(加法器或计算器)不应该错过。
【问题讨论】:
-
这里真正需要配置什么:获取锁的超时时间,获取锁的方法(
tryLock/lock)还是别的什么?如果这些都不是,那你为什么要暴露锁? -
我可以保持私有锁,并从 ElementAdder 和 StatisticsCalculator 中完全取消它。但是,我的问题是,这是正确的方法吗
-
这取决于视角。如果它是一些真实产品的代码,可能会被其他开发人员访问,那么这种方法是不可行的:你的类的用户必须了解一些内部细节,这种方法很容易出错。如果它是一次性使用的代码,并且您永远不会再使用它,那么它可能是一个合理的解决方案。此外,您没有回答任何相关问题(“您真正需要在此处配置什么”部分)。
标签: java reentrantlock