【问题标题】:Java - Valid Object Pool with fixed number of Objects to be pooled and use wait-notifyJava - 具有固定数量的对象的有效对象池要池化并使用等待通知
【发布时间】:2018-07-20 09:30:20
【问题描述】:

我正在尝试实现具有固定数量的对象可用于池的对象池,如果池为空则使用等待,并在线程释放对象时通知。

我可以使用下面的程序实现上述所需的功能。

我想知道实施是否正确或从面试的角度需要任何修改?

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

【问题讨论】:

  • 我会问以防万一:您是否知道免费提供的对象池实现,例如Apache Commons Pool?除非您将此作为一种编码练习,否则您应该使用现有的库。
  • 是的,它需要大量修改。除非你面试的是一个非常初级的角色,否则这种对同步的幼稚使用会引发巨大的危险信号。 staticJust Wrong TM
  • 嗨@BoristheSpider,您能否分享所需的修改或任何我可以用来理解正确实现的链接形式,TM 意味着?
  • 抱歉,没有任何代码是可挽救的。我建议丢弃它并学习如何使用ArrayBlockingQueue。如果你想看看如何正确实现一个池,那么 Apache Commons Pool 是open source
  • 另一件事 - 要进行全面的代码审查,您可以尝试 Code Review SE

标签: java design-patterns object-pooling objectpool


【解决方案1】:

很久以前,我使用类似于您的抽象解决了类似的问题。幸运的是,我保存了它并把它放在here。为了保持这个答案简短并希望我的话能清楚,我不会在这里发布整个代码。


实施:

您可以拥有一个具有泛型的抽象类,它可以让您创建自己喜欢的对象的池。是的,我会像这样使用最喜欢的并逃脱它

这个抽象类让其实现者处理创建/过期对象的逻辑。

这个类有一个队列,用于存放锁定解锁的对象。

当您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;
    }   

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 2016-10-24
    • 1970-01-01
    • 2015-07-11
    • 1970-01-01
    相关资源
    最近更新 更多