我有一个客户端 - 服务器架构,其中服务器的客户端轮流工作,每次客户端应该工作时传递一个参数。客户端使用参数,当完成后,参数变为“无效”,不能再用于工作。
我希望在此过程中避免运行垃圾收集器,因此我避免了对象分配。因此,计划是服务器将单个参数对象与每个客户端关联,并且每次要求客户端执行工作时,它将始终传递相同的参数。但是,这会产生一个问题,即必须将参数重新设置为“有效”,同时还要确保客户端(可能保留了对上次参数的引用)无法开始使用它(比如说) ,在被要求开始工作之前,在另一个线程中。
因此,所有参数的公共方法都被同步,并且设置了“有效”状态,然后在beginWork
块内对客户端进行(同步)synchronized
调用。但这会产生客户端在不知不觉中持有参数锁定的问题,如果客户端想要将其工作分成多个线程,则可能会导致问题。所以我介绍了一个单线程ExecutorService
,服务器使用它来分叉对beginWork
的调用,这可以确保服务器立即释放锁。但这对我来说似乎是一个糟糕的设计 - 为什么这个类需要一个完整的其他线程?
所以我的问题是:鉴于我刚刚提出的所有内容,我是否犯了一些可怕的设计错误,导致我使这个课程过于复杂化,还是真的需要这么复杂?
interface Client {
public void doWork(Param p);
}
interface Param {
public boolean isValid();
}
class Server {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private final MyParam[] params;
private class MyParam implements Param {
boolean isValid;
Client client;
Runnable task = new Runnable() {
@Override
public void run() {
client.doWork(MyParam.this);
}
}
@Override
public synchronized boolean isValid() {
return isValid;
}
}
public void runClients() {
while (true) {
for (MyParam param : params) {
synchronized(param) {
param.isValid = true;
// fork the client so we release the lock promptly (ugly!)
executor.execute(param.task);
}
// ... wait for the client to finish ...
}
}
}
}
答案 0 :(得分:0)
我通过向ReentrantLock
接口添加显式Param
来解决此问题。因此,我只是锁定了参数,而不是使用同步块,如果他愿意,让客户端解锁它。