我正在使用对象池设计模式()来练习我自己。并创建了示例并试图运行我的代码。
程序在池中提供有限数量的对象,并提供异步进程的运行数。
我的代码只需从池中选择一个对象(如果没有可用的对象,并且对象的数量低于限制,则创建新对象),然后在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上调试它,然后我看到线程处于休眠状态之后,它就会进入监视状态。我对多线程很陌生,所以我不知道这是否正常。
如能提供任何帮助,将不胜感激。
发布于 2019-12-12 18:52:36
您已经使ObjectPool的方法同步了。
这意味着没有线程可以“释放”一个对象(如果有任何线程已经“获取”了一个对象synchronized releaseObject(T o),则为synchronized releaseObject(T o)。
与其使整个方法同步,不如找到一种只对inUse/available原子进行修改的方法。
尝试从"getObject“中删除同步,而只同步列表中的第一个添加/删除,如下所示:
public T getObject() {
if (!available.isEmpty()) {
synchronized(this) {
T o = available.remove(0);
inUse.add(o);
}
return o;
}
....发布于 2019-12-12 18:54:11
一个线程在连续递归中调用getObject()。因为这个线程持有池上的锁(getObject()是同步的),所以任何线程都不能将对象返回到池(因为releaseObject()是同步的)。
在实现池时,使用不阻止资源释放的并发数据结构。发布应该始终是非阻塞的。
发布于 2019-12-12 19:45:47
在这里,ojbect锁定的情况出现在图片中。当线程(Abc)将调用同步 getobject() n次时。它将保持锁,以便在此之前没有线程能够访问同步 getRelease()方法。签出以下创建对象池的方法。
或
您可以使用java阻塞队列来创建对象池。阻塞队列也是线程安全的。
或
请参阅下面的链接以创建对象池https://dzone.com/articles/generic-and-concurrent-object
https://stackoverflow.com/questions/59310914
复制相似问题