具有大小受限资源池的多线程Java worker
我有一个“Worker”类,它使用一个资源“Client”。 可以有任意数量的线程在任何给定时间运行“Worker”。 “客户端”不是线程安全的,因此我使用“ThreadLocal”来表示它。 “客户机”连接到某个服务器,并执行一个HTTP“请求”,工作人员向“客户机”提供信息具有大小受限资源池的多线程Java worker,java,multithreading,synchronization,thread-safety,worker,Java,Multithreading,Synchronization,Thread Safety,Worker,我有一个“Worker”类,它使用一个资源“Client”。 可以有任意数量的线程在任何给定时间运行“Worker”。 “客户端”不是线程安全的,因此我使用“ThreadLocal”来表示它。 “客户机”连接到某个服务器,并执行一个HTTP“请求”,工作人员向“客户机”提供信息 public class Worker { // Client is NOT thread-safe !!! private static ThreadLocal<Client> client = new
public class Worker {
// Client is NOT thread-safe !!!
private static ThreadLocal<Client> client = new ThreadLocal<Client>();
@Override
protected void onGet(Request req) {
handleRequest(req);
}
private void handleRequest(Request req) {
someRunnableExecutor(new Runnable() {
@Override
public void run() {
get_client().send_req(req);
}
});
}
private Client get_client() {
Client c = client.get();
if (c == null) {
c = new Client();
client.set(c);
}
return c;
}
公共类工作者{
//客户端不是线程安全的!!!
私有静态ThreadLocal客户端=新ThreadLocal();
@凌驾
受保护的void onGet(请求请求){
HandlerRequest(需求);
}
私有无效句柄请求(请求请求){
someRunnableExecutor(新的Runnable(){
@凌驾
公开募捐{
获取客户端()。发送请求(req);
}
});
}
私有客户端get_Client(){
Client c=Client.get();
如果(c==null){
c=新客户端();
client.set(c);
}
返回c;
}
在当前的实现(如上)中,为了清晰起见,将其精简为“活动”的“客户机”和运行的“工作者”一样多
这是一个问题,因为服务器正在耗尽
我所能做的只是修复“Worker”。无法访问“客户端”、服务器或运行Worker的执行器
我想做的是在“Worker”中有一个由“Client”组成的队列和一段同步代码,将“Client”从队列中移除,如果队列是空的,“Worker”应该等待队列中有一个客户端,然后将“Client”放回队列中-也同步
我真的想让它尽可能简单,对代码所做的更改尽可能少
没有新的类,没有工厂,只有一些数据结构来保存“客户端”和同步
一般来说,我对如何实现这一点有点困惑,同时也对“客户端”不是线程安全的,我必须将其“线程本地化”这一事实感到困惑。这是我如何将其放入队列中的吗
private static Queue<ThreadLocal<CLient>> queue =
new LinkedList<ThreadLocal<CLient>>();
专用静态队列=
新建LinkedList();
另外,我如何/在哪里初始化队列,一次,比如说5个客户端
请分享您的想法。您不需要在此处使用ThreadLocal,因为您希望客户端数量少于Workers。您所需要的一切都在BlockingQueue中。 注意!我假设客户端的send_req是同步的,如果不是的话-代码需要在run()方法中进行一些更改
公共类工作者{
专用静态最终整型客户端\u编号=5;
私有静态最终阻塞队列=新的LinkedBlockingQueue(客户端号);
静止的{
对于(int i=0;i
对线程安全问题使用BlockingQueue或ConcurrentQueue我不明白为什么这是一个问题。将您的客户机或某些任务(如工作人员)放入在一个队列中,一次只取出一个。到底是什么问题?的确。我一开始并没有弄清楚,但我在这里需要的是线程安全的队列实现。是的,您关于发送请求同步的假设是正确的。感谢您提供了额外的代码示例。我接受了您的答案并投票通过但是投票结果并没有显示我在stackoverflow上的声望不够高。
public class Worker {
private static final int CLIENTS_NUMBER = 5;
private static final BlockingQueue<Client> queue = new LinkedBlockingQueue<>(CLIENTS_NUMBER);
static {
for (int i = 0; i < CLIENTS_NUMBER; i++)
queue.put(new Client());
}
@Override
protected void onGet(Request req) {
handleRequest(req);
}
private void handleRequest(Request req) {
someRunnableExecutor(new Runnable() {
@Override
public void run() {
try {
Client client = takeClient();
client.send_req(req);
putClient(client);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
}
private Client takeClient() throws InterruptedException {
return queue.take();
}
private void putClient(Client client) throws InterruptedException {
queue.put(client);
}
}