4

サービス チケットに関連するデータを 1 つのスレッドだけが変更できるようにする方法が必要です。複数のスレッドが同時にチケット データを変更しようとしている可能性があります。

以下は、私のアプローチの簡略版です。これを行うより良い方法はありますか?おそらくjava.util.concurrentパッケージで?

public class SomeClass1
{
    static final HashMap<Integer, Object> ticketLockMap = new HashMap<Integer, Object>();


    public void process(int ticketNumber)
    {
        synchronized (getTicketLock(ticketNumber))
        {
            // only one thread may modify ticket data here

            // ... ticket modifications here...
        }
    }


    protected static Object getTicketLock(int ticketNumber)
    {
        Object ticketLock;

        // allow only one thread to use map
        synchronized (ticketLockMap)
        {
            ticketLock = ticketLockMap.get(ticketNumber);

            if (ticketLock == null)
            {
                // first time ticket is locked
                ticketLock = new Object();
                ticketLockMap.put(ticketNumber, ticketLock);
            }
        }

        return ticketLock;
    }
}

さらに、未使用のロックで HashMap をいっぱいにしたくない場合は、次のようなより複雑なアプローチが必要になります。

public class SomeClass2
{
    static final HashMap<Integer, Lock> ticketLockMap = new HashMap<Integer, Lock>();


    public void process(int ticketNumber)
    {
        synchronized (getTicketLock(ticketNumber))
        {
            // only one thread may modify ticket data here

            // ... ticket modifications here...

            // after all modifications, release lock
            releaseTicketLock(ticketNumber);
        }
    }


    protected static Lock getTicketLock(int ticketNumber)
    {
        Lock ticketLock;

        // allow only one thread to use map
        synchronized (ticketLockMap)
        {
            ticketLock = ticketLockMap.get(ticketNumber);

            if (ticketLock == null)
            {
                // first time ticket is locked
                ticketLock = new Lock();
                ticketLockMap.put(ticketNumber, ticketLock);
            }
        }

        return ticketLock;
    }


    protected static void releaseTicketLock(int ticketNumber)
    {
        // allow only one thread to use map
        synchronized (ticketLockMap)
        {
            Lock ticketLock = ticketLockMap.get(ticketNumber);

            if (ticketLock != null && --ticketLock.inUseCount == 0)
            {
                // lock no longer in use
                ticketLockMap.remove(ticketLock);
            }
        }
    }
}


class Lock
{
    // constructor/getters/setters omitted for brevity
    int inUseCount = 1;
}
4

1 に答える 1

1

Lockインターフェイスを探しているかもしれません。ReentrantLock2 番目のケースは、ロックされた回数をカウントするによって解決できます。

ロックには.lock()、ロックが取得されるのを待つメソッドと、次の.unlockように呼び出されるメソッドがあります

 Lock l = ...;
 l.lock();
 try {
     // access the resource protected by this lock
 } finally {
     l.unlock();
 }

これは、 と組み合わせることができますHashMap<Integer, Lock>。呼び出しを省略してsynchronized、コード行を削減できます。

于 2016-03-30T14:47:30.287 に答える