用阻止队列并发替换链表

问题描述 投票:0回答:1

我已经为https://www.programcreek.com/2014/08/leetcode-design-phone-directory-java/实现了一个解决方案,如下面的清单1所示:

class PhoneDirectory {
    private final LinkedList<Integer> q;
    private final boolean[] used;

    public PhoneDirectory(int maxNumbers) {
        q = new LinkedList<>();
        used = new boolean[maxNumbers];
        for (int i = 0; i < maxNumbers; i++) {
            q.offer(i);
        }
    }

    public int get() {
        if (!q.isEmpty()) {
            int num = q.poll();
            used[num] = true;
            return num;
        }
        return -1;
    }

    public void release(int number) {
        if (used[number]) {
            used[number] = false;
            q.offer(number);
        }
    }
}

但是,以上解决方案是单线程的,如果多个线程同时访问PhoneDirectory对象,它将失败。

因此,我在下面的清单2中实现了线程安全版本,其逻辑略有不同:

public class PhoneDirectory {

    private int curr;
    private final int[] next;
    private final Object lock = new Object();
    private final long SLEEP = 2000;

    public PhoneDirectory(int size) {
        next = new int[size];
        curr = 0;
        for (int i = 0; i < size; i++) {
            next[i] = (i + 1) % size;
        }
    }

    public int get(final long sleepInSeconds) throws InterruptedException {
        synchronized (lock) {
            final long sleepInMills = sleepInSeconds * 1000;
            long startTime = System.currentTimeMillis();
            try {
                while (next[curr] == -1) {
                    if (System.currentTimeMillis() - startTime >= sleepInMills) {
                        return -1;
                    }
                    lock.wait(SLEEP);
                }
                int res = curr;
                curr = next[curr];
                next[res] = -1;
                return res;
            } finally {
                lock.notify();
            }
        }
    }

    public void release(int number) {
        synchronized (lock) {
            try {
                if (next[number] != -1) {
                    return;
                }
                next[number] = curr;
                curr = number;
            } finally {
                lock.notify();
            }
        }
    }
}
  1. 清单2是否真的是线程安全的?那是实现线程安全代码的正确方法吗?
  2. 它是否可扩展,例如如果有100个线程和数百万个数字?
  3. 我可以简单地用LinkedBlockingQueue(在清单1中)替换LinkedList并期望它是线程安全的吗?比上面的清单2好吗?
java multithreading linked-list blockingqueue
1个回答
0
投票

免责声明:我不是在看代码的内部机制,而只是在线程方面。

© www.soinside.com 2019 - 2024. All rights reserved.