gpt4 book ai didi

java - newFixedThreadPool 无法按预期使用对象池

转载 作者:搜寻专家 更新时间:2023-11-01 03:42:48 26 4
gpt4 key购买 nike

我正在努力弄清楚如何集中资源,我开始怀疑我的线程可能是问题所在(不是 100%,但一直在试验)。我想要做的事情的要点是创建一个服务器 channel 池,然后查看线程是否正在使用它们。我已经成功地获得了为我正在上传的项目创建的 channel 数量(即它没有合并并且只是在每个线程中创建新 channel )并且成功地只创建了一个 channel (即不合并或创建新 channel 需要的 channel )。

我在想也许线程与池交互的方式是问题所在,所以我尝试创建 newCachedThreadPool 这样只要有工作线程就不会死,但是当我这样做时我得到错误说正在使用的 channel 已关闭。我的池中有一个 destroyObject 方法,但我从未调用过它,所以我不明白为什么它会被触发(如果我将其注释掉然后它会起作用但只创建一个 channel 并且上传速度非常非常慢大约 300 次操作/秒与没有线程池我得到 30k/秒)。我怀疑它正在终止,是否有任何方法可以验证这一点,如果它正在终止,我可以使用替代方案吗?

这是代码(忽略所有 rabbitmq 的东西,只是为了让我可以监控结果):

import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;

import java.io.IOException;
import java.util.NoSuchElementException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.MessageProperties;

public class PoolExample {

private static ExecutorService executor_worker;

static {
final int numberOfThreads_ThreadPoolExecutor = 20;
executor_worker = Executors.newCachedThreadPool();
executor_worker = new ThreadPoolExecutor(numberOfThreads_ThreadPoolExecutor, numberOfThreads_ThreadPoolExecutor, 1000, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>());
}

private static ObjectPool<Channel> pool;

public static void main(String[] args) throws Exception {
System.out.println("starting..");
ObjectPool<Channel> pool =
new GenericObjectPool<Channel>(
new ConnectionPoolableObjectFactory(), 50);
for (int x = 0; x<500000000; x++) {
executor_worker.submit(new MyRunnable(x, pool));
}
//executor_worker.shutdown();
//pool.close();
}
}

class ConnectionPoolableObjectFactory extends BasePoolableObjectFactory<Channel> {
Channel channel;
Connection connection;

public ConnectionPoolableObjectFactory() throws IOException {
System.out.println("hello world");
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
channel = connection.createChannel();
}

@Override
public Channel makeObject() throws Exception {
//channel = connection.createChannel();
return channel;
}

@Override
public boolean validateObject(Channel channel) {
return channel.isOpen();
}

@Override
public void destroyObject(Channel channel) throws Exception {
channel.close();
}

@Override
public void passivateObject(Channel channel) throws Exception {
//System.out.println("sent back to queue");
}
}

class MyRunnable implements Runnable{
protected int x = 0;
protected ObjectPool<Channel> pool;

public MyRunnable(int x, ObjectPool<Channel> pool) {
// TODO Auto-generated constructor stub
this.x = x;
this.pool = pool;
}

public void run(){
try {
Channel channel = pool.borrowObject();
String message = Integer.toString(x);
channel.basicPublish( "", "task_queue",
MessageProperties.PERSISTENT_TEXT_PLAIN,
message.getBytes());
pool.returnObject(channel);
} catch (NoSuchElementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

附注我基本上问了几个问题并阅读了文档并试图弄清楚这一点,一路走来我可能完全走错了方向,所以如果您看到任何问题或提示,请将它们发送给我。

情节变厚了:

在 main 方法的 for 循环中(我将工作提交给线程的地方)我添加了:

    Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
System.out.println(threadSet.size()); //number of threads
System.out.println(pool.getNumActive());

它显示池中有 25 个线程(虽然我说是 20 个)和 20 个项目。但是当我查看 rabbitmq UI 时,我看到一个连接只有一个 channel 。如果我创建 channel 并提交给可运行的,那么它会创建许多 channel (但它永远不会关闭它们)。我不明白这是怎么回事,为什么结果不如预期。

最佳答案

我认为问题在于您的 ConnectionPoolableObjectFactory 只创建了一个 Channel 对象。似乎每次调用 makeObject 时都应该创建一个新的 Channel。

所以也许应该这样实现:

public class ConnectionPoolableObjectFactory
extends BasePoolableObjectFactory<Channel> {

private final Connection connection;

private ConnectionPoolableObjectFactory() {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
connection = factory.newConnection();
}

@Override
public Channel makeObject() throws Exception {
return connection.createChannel();
}

@Override
public boolean validateObject(Channel channel) {
return channel.isOpen();
}

@Override
public void destroyObject(Channel channel) throws Exception {
channel.close();
}

@Override
public void passivateObject(Channel channel) throws Exception {
//System.out.println("sent back to queue");
}
}

这假设每个工厂从单个连接创建多个 channel 。

关于java - newFixedThreadPool 无法按预期使用对象池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10417773/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com