Java - Действительный пул объектов с фиксированным количеством объектов, которые должны быть объединены и использовать wait-notify
Я пытаюсь реализовать пул объектов, который имеет фиксированное количество объектов, доступных для пула, и использую ожидание, если пул пуст, и уведомляю, когда поток освобождает объект.
Я могу достичь вышеуказанной необходимой функциональности, используя приведенную ниже программу.
Я хочу знать, является ли реализация правильной или нуждается в какой-либо модификации с точки зрения интервью?
import java.util.ArrayList;
import java.util.List;
class ObjectPool
{
static List objects = new ArrayList();
static
{
objects.add("Object One");
objects.add("Object Two");
}
public Object getObject()
{
synchronized(objects)
{
if(objects.isEmpty())
{
System.out.println(Thread.currentThread().getName() + " waiting as Object Pool is empty");
try {
objects.wait();
System.out.println(Thread.currentThread().getName() + " Got Notification");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Object locked = objects.get(objects.size()-1);
objects.remove(locked);
System.out.println(Thread.currentThread().getName() + " got lock of object : "+ locked);
return locked;
}
}
public boolean release(Object released)
{
synchronized(objects)
{
System.out.println(Thread.currentThread().getName() + " releasing Object : "+released);
objects.notify();
return objects.add(released);
}
}
}
public class MainforObjectPool implements Runnable
{
static ObjectPool p = new ObjectPool();
public static void main(String[] args)
{
MainforObjectPool m = new MainforObjectPool();
Thread t1 = new Thread(m,"thread 1");
Thread t2 = new Thread(m,"thread 2");
Thread t3 = new Thread(m,"thread 3");
Thread t4 = new Thread(m,"thread 4");
Thread t5 = new Thread(m,"thread 5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
System.out.println("Main Thread Completed");
}
public void run()
{
Object locked = p.getObject();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
p.release(locked);
}
}
1 ответ
Давным-давно я решил подобную проблему, используя абстракцию, похожую на вашу. К счастью, я сохранил его и положил здесь. Ради краткости этого ответа и, надеюсь, ясности моих слов, я не буду публиковать здесь весь код.
Реализация:
У вас может быть абстрактный класс, имеющий обобщенный тип, который позволяет вам создавать пулы ваших любимых объектов. Да, я буду использовать любимый, как это и сойдет с рук
Этот абстрактный класс позволяет его разработчикам обрабатывать логику создания / истечения срока действия объектов.
Этот класс имеет очередь для объектов, которые заблокированы и разблокированы.
Когда ты checkIn
объект в пуле, он попадает в разблокированную очередь.
Когда ты checkOut
объект из пула, он проверяет, истек ли срок действия объекта, вызывая абстрактный метод validate()
, Если эта функция возвращает true
Затем объект перемещается в заблокированную очередь. Если эта функция возвращает false
затем объект удаляется из пула и срок его действия истекает путем вызова абстрактной функции expire()
(ты можешь использовать notify
в этом). Если извлекаемый объект не объединяется, он создается и помещается в заблокированную очередь.
Код:
public abstract class ObjectPool<T> {
private long expirationTime;
private Hashtable<T, Long> locked, unlocked;
public ObjectPool() {
expirationTime = 30000; // 30 seconds
locked = new Hashtable<T, Long>();
unlocked = new Hashtable<T, Long>();
}
/**
* Implemented in concrete class. Create an object to be pooled.
*/
protected abstract T create();
/**
* Used to check whether the object should be kept in the lock, or released.
*/
public abstract boolean validate(T o);
/**
* Object expired. (Use notify?)
*/
public abstract void expire(T o);
public synchronized T checkOut() {
long now = System.currentTimeMillis();
T t;
if (unlocked.size() > 0) {
Enumeration<T> e = unlocked.keys();
while (e.hasMoreElements()) {
t = e.nextElement();
if ((now - unlocked.get(t)) > expirationTime) {
// object has expired
unlocked.remove(t);
expire(t);
t = null;
} else {
if (validate(t)) {
unlocked.remove(t);
locked.put(t, now);
return (t);
} else {
// object failed validation
unlocked.remove(t);
expire(t);
t = null;
}
}
}
}
// no objects available, create a new one
t = create();
locked.put(t, now);
return (t);
}
public synchronized void checkIn(T t) {
locked.remove(t);
unlocked.put(t, System.currentTimeMillis());
}
public synchronized long getExpirationTime() {
return expirationTime;
}
public synchronized void setExpirationTime(long expirationTime) {
this.expirationTime = expirationTime;
}
}