我正在使用Java的对象池设计模式来实践自己。并创建示例并尝试运行我的代码。
程序在池中提供有限数量的对象,并在异步进程中提供运行数量。
我的代码只需从池中拾取一个对象(如果没有可用对象并且对象数小于限制,则创建新对象),然后在Thread.sleep
之后返回。但是以某种方式,其他线程继续循环运行,找不到任何可用的对象。
public abstract class ObjectPool<T> {
private long waitingTime;
private int maxObjectPoolSize;
private final List<T> available = Collections.synchronizedList(new ArrayList<>());
private final List<T> inUse = Collections.synchronizedList(new ArrayList<>());
protected AtomicInteger count = new AtomicInteger(0);
private AtomicBoolean waiting = new AtomicBoolean(false);
public abstract T create();
public ObjectPool(int poolSize) {
waitingTime = 1200;
setMaxObjectPoolSize(poolSize);
}
public void setMaxObjectPoolSize(int poolSize) {
this.maxObjectPoolSize = poolSize;
}
public synchronized T getObject() {
if (!available.isEmpty()) {
T o = available.remove(0);
inUse.add(o);
return o;
}
// if max pool size, wait for object to be released
if(count.get() == maxObjectPoolSize) {
this.waitUntilNextAvailable();
return this.getObject();
}
// if no objects available, create new one
T o = this.create();
this.inUse.add(o);
return o;
}
public synchronized void releaseObject(T o) {
this.inUse.remove(o);
this.available.add(o);
System.out.println(o.toString() + " is free");
}
private void waitUntilNextAvailable() {
// if (waiting.get()) {
// waiting.set(false);
// throw new ObjectNotFoundException("No Object Available");
// }
// waiting.set(true);
System.out.println(Thread.currentThread().getName());
waiting(waitingTime);
}
public void waiting(long ms) {
try {
TimeUnit.MILLISECONDS.sleep(ms);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
public class ProcessThread implements Runnable {
private RoomPool pool;
public ProcessThread(RoomPool pool) {
this.pool = pool;
}
@Override
public void run() {
takeAnObject();
}
private void takeAnObject() {
try {
System.out.println("New process: " + Thread.currentThread().getName());
Room room = pool.getObject();
TimeUnit.MILLISECONDS.sleep(randInt(1000, 1500));
pool.releaseObject(room);
System.out.println("executed: " + Thread.currentThread().getName());
} catch (InterruptedException | ObjectNotFoundException e) {
System.out.println(">>>> Process Rejected: " + Thread.currentThread().getName());
}
}
private static int randInt(int min, int max) {
return new Random().nextInt((max - min) + 1) + min;
}
}
public class Main {
public static final int OBJECT_POOL_SIZE = 4;
public static final int NUMBER_OF_PROCESSES = 10;
public static void main(String[] args) {
RoomPool pool = new RoomPool(OBJECT_POOL_SIZE);
for (int i = 1; i <= NUMBER_OF_PROCESSES; i++) {
Runnable process = new ProcessThread(pool);
Thread thread = new Thread(process);
thread.start();
}
}
}
New process: Thread-5
New process: Thread-8
New process: Thread-3
New process: Thread-0
New process: Thread-4
New process: Thread-6
New process: Thread-7
New process: Thread-2
New process: Thread-1
New process: Thread-9
Room name = Room 1 is created
Room name = Room 2 is created
Room name = Room 3 is created
Room name = Room 4 is created
Thread-7
Thread-7
Thread-7
Thread-7
Thread-7
Thread-7
我不知道为什么线程不会返回池中的对象。
我试图在我的IDE上调试它,然后看到线程处于SLEEP状态,然后进入MONITOR。我是这种多线程技术的新手,所以我不知道这是否正常。
任何帮助将不胜感激
答案 0 :(得分:2)
您已使ObjectPool
的方法同步。
这意味着没有线程可以“释放”对象({synchronized releaseObject(T o)
,如果有任何线程已经“获取”对象synchronized getObject()
。
与其让整个方法同步,不如找到一种方法来仅修改inUse / available atomic。
尝试从“ getObject”中删除已同步的对象,而是仅同步列表中的第一次添加/删除,例如:
public T getObject() {
if (!available.isEmpty()) {
synchronized(this) {
T o = available.remove(0);
inUse.add(o);
}
return o;
}
....
答案 1 :(得分:2)
一个线程正在连续递归中调用getObject()
。因为此线程将锁锁定在池上(getObject()
已同步),所以任何线程都无法将对象返回到池中(因为releaseObject()
已同步)。
在实现池时,请使用不会阻止资源释放的并发数据结构。发布应该始终是非阻塞的。
答案 2 :(得分:1)
这里出现了对象锁定的情况。线程(abc)将调用 synchronized getobject()达n次。它将保持锁定状态,以便在此之前,没有线程能够访问同步 getRelease()方法。查看以下创建对象池的方法。
OR
您可以使用Java阻塞队列来创建对象池。阻塞队列也是线程安全的。
OR
请参考下面的链接来创建对象池 https://dzone.com/articles/generic-and-concurrent-object