具有大小受限资源池的多线程Java worker

具有大小受限资源池的多线程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

我有一个“Worker”类,它使用一个资源“Client”。 可以有任意数量的线程在任何给定时间运行“Worker”。 “客户端”不是线程安全的,因此我使用“ThreadLocal”来表示它。 “客户机”连接到某个服务器,并执行一个HTTP“请求”,工作人员向“客户机”提供信息

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);
    }
}