尝试实施同步队列适得其反

时间:2018-12-03 11:42:24

标签: java multithreading synchronization queue

我正在尝试使用监视器来实现自己的同步队列。通常,<我会使用已经实现的队列,但是我是线程技术的新手,我想看看幕后情况。我的逻辑将一个Linked-List包装在一个类中,沿着一个最大容量和一个当前容量,再加上一个标志,该标志指示另一端没有写程序(类似于C管道)。

工作方式:

  • PUSH :虽然当前容量是最大容量,但我们等待。否则,我们将礼物添加到链接列表中并增加容量,然后通知。
  • tryPOP :当前容量为0时,请等待。否则将礼物存储在一个临时变量中,将其返回,然后是一个finally块,该块将打印出来(使用对象的toString())以将其打印出来。如果达到超时,它将返回null,并且调用对象应再次尝试。 (我这样做是为了防止死锁)

似乎出了什么问题:每当我向队列中添加某些内容时,我也会打印添加的内容和当前容量。我发现容量超过了最大容量,而且由于所有方法都是同步的并且

现在,输入一些代码:

public class GiftQueue {
    private final Queue<Gift> factoryGiftQueue;
    private final int queueCapacity;
    private volatile int currentCapacity;
    private volatile boolean writingEndClosed;


    public GiftQueue(Queue<Gift> factoryGiftQueue, int queueCapacity) {
        this.factoryGiftQueue = factoryGiftQueue;
        this.queueCapacity = queueCapacity;
        this.currentCapacity = 0;
        this.writingEndClosed = false;

    }

    public synchronized void push(Gift gift) {
        while (currentCapacity == queueCapacity) {
            try {
                System.out.println("Queue full, awaiting pop...");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        factoryGiftQueue.add(gift);
        currentCapacity++;
        System.out.println("Gift " + gift + " has been added to the queue. Queue size: " + currentCapacity);
        notifyAll();
    }


    public synchronized Gift tryPop(int timeoutNanos) {
        while (currentCapacity == 0) {
            try {
                System.out.println("Queue is empty, awaiting new push...");
                wait();
                if (currentCapacity == 0) {
                    System.out.println("Pop ABORTED");
                    return null;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


        }
        Gift temp = factoryGiftQueue.poll();
        --currentCapacity;

        notifyAll();

        try {
            return temp;
        } finally {
            System.out.println("Gift has" + temp + " been pulled from queue. Queue size " + currentCapacity);
        }


    }

    public synchronized void close() {
        System.out.println("Writing end has been closed !");
        writingEndClosed = true;
    }


    public synchronized boolean isAvailable() {
        return (!(writingEndClosed) || currentCapacity != 0);
    }

    public synchronized boolean notEmpty() {
        return currentCapacity != 0;
    }

    public synchronized boolean isFull() {
        return currentCapacity == queueCapacity;
    }

    public synchronized boolean isEmpty() {
        return currentCapacity == 0;
    }
}

呼叫者对象是:

public class Reindeer implements Runnable {
    private final int ID;
    private final GiftQueue factoryQueue;
    private final GiftQueue santaGiftQueue;
    private final Semaphore serviceQueue;

    public Reindeer(int ID, GiftQueue factoryQueue, GiftQueue santaGiftQueue,
                    Semaphore serviceQueue) {
        this.ID = ID;
        this.factoryQueue = factoryQueue;
        this.santaGiftQueue = santaGiftQueue;
        this.serviceQueue = serviceQueue;
    }

    @Override
    public void run() {
        while (factoryQueue.isAvailable()) {
            Gift gift = null;
            System.out.println("Reindeer " + ID + " working");
            try {
                serviceQueue.acquire();
                if (factoryQueue.isEmpty()) {
                    serviceQueue.release();
                    continue;
                }
                gift = factoryQueue.tryPop(10);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                serviceQueue.release();
            }
            if (gift != null) {
                santaGiftQueue.push(gift);
                System.out.println("Reindeer " + ID + " sent a gift");
            } else {
                System.out.println("Reindeer " + ID + " will try again ");
                awaitRandom();
            }

        }

        System.out.println("Reindeer " + ID + " finished");
    }

    private void awaitRandom() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return ID + "";
    }

}

public class Factory implements Runnable {
    private static final PositionBuilder positionBuilder = new PositionBuilder();
    private final int maxGifts;
    private final int factoryID;
    private final int matrixSize;
    private final int numberOfElves;
    private final GiftQueue giftQueue;
    private final Thread[] elvesThreads;
    private final ArrayList<ElfRunnable> elves = new ArrayList<>();
    private static final ElfBuilder elfBuilder = new ElfBuilder();
    private final FactoryElfMap elfMap;
    private final Semaphore reindeerSemaphore;
    private final WorkshopStatus workshopStatus;
    private final Semaphore serviceQueue;
    private final Orchestrator orchestrator;
    private int producedGifts;


    public Factory(int factoryID, int numberOfToysTobeProduced, int matrixSize, int numberOfElves,
                   GiftQueue giftQueue, Orchestrator orchestrator,
                   FactoryElfMap elfMap,
                   Semaphore reindeerSemaphore,
                   WorkshopStatus workshopStatus,
                   Semaphore serviceQueue) {
        this.factoryID = factoryID;
        this.maxGifts = numberOfToysTobeProduced;
        this.matrixSize = matrixSize;
        this.numberOfElves = numberOfElves;
        this.giftQueue = giftQueue;
        this.orchestrator = orchestrator;
        this.elfMap = elfMap;
        this.reindeerSemaphore = reindeerSemaphore;
        this.workshopStatus = workshopStatus;
        this.serviceQueue = serviceQueue;
        this.producedGifts = 0;
        this.elvesThreads = new Thread[numberOfElves];
        System.out.println(numberOfElves);
    }

    @Override
    public void run() {
        createElves();
        startElves();

        while (goalNotAchieved()) {
            orchestrator.awaitSupervisorTurn();
            System.out.println("Factory " + factoryID + " is working..");
            queryPositions();
            orchestrator.setWorkersTurn();


        }
        joinElves();

        System.out.println("Factory " + factoryID + " FINISHED");


        workshopStatus.signalDone();
        giftQueue.close();
    }

    public synchronized boolean goalNotAchieved() {
        return !(producedGifts == maxGifts);
    }


    private void joinElves() {
        for (int i = 0; i < numberOfElves; i++) {
            try {
                elvesThreads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void startElves() {
        for (int i = 0; i < numberOfElves; i++) {
            elvesThreads[i].start();
        }
    }

    private void createElves() {
        for (int i = 0; i < numberOfElves; i++) {
            IPosition elfPosition = positionBuilder.create(matrixSize, elfMap);
            ElfRunnable elfRunnable = elfBuilder.create(i, this, elfPosition,
                                                        orchestrator);
            elfMap.addEntry(elfRunnable, elfPosition);
            elfPosition.setOwner(elfRunnable);
            elvesThreads[i] = new Thread(elfRunnable);
        }
    }

    private synchronized void queryPositions() {
        try {
            reindeerSemaphore.acquire();
            System.out.println("Factory " + factoryID + " starting query....");
            for (ElfRunnable elf : elves) {
                System.out.println("   Queried " + elf + ": (" + elf.getElfPosition() + ")");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reindeerSemaphore.release();
        }

    }


    public synchronized void becomeAware(ElfRunnable elf) {
        System.out.println("Factory " + factoryID + " got new elf");
        elves.add(elf);
    }

    public synchronized void notifyGiftCreated(Gift gift) {
        try {
            reindeerSemaphore.acquire();
            if (producedGifts == maxGifts) {
                orchestrator.setWorkersTurn();
                System.out.println("Rejecting " + gift);
            } else {
                serviceQueue.acquire();
                producedGifts++;

                if (giftQueue.isFull()) {
                    serviceQueue.release();
                    reindeerSemaphore.release();
                    notifyGiftCreated(gift);
                    return;
                }
                giftQueue.push(gift);
                System.out.println("GIFTS: " + producedGifts);
                serviceQueue.release();

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            reindeerSemaphore.release();
        }




    }


    @Override
    public String toString() {
        return factoryID + "";
    }


}

示例输出:

Gift Gift-1329879510-34 has been added to the queue. Queue size: 1
GIFTS: 400
Reindeer 0 working
Gift hasGift-1329879510-34 been pulled from queue. Queue size 0
released
Gift Gift-1329879510-34 has been added to the queue. Queue size: 400 // <--- ???
Reindeer 1 sent a gift
Reindeer 1 working
released
Reindeer 0 working
Gift Gift-1015004123-1 has been added to the queue. Queue size: 1
GIFTS: 401
Gift hasGift-1015004123-1 been pulled from queue. Queue size 0
released
Queue full, awaiting pop...
released
Reindeer 0 working
Gift Gift--1853705096-37 has been added to the queue. Queue size: 1
GIFTS: 402
Gift hasGift--1853705096-37 been pulled from queue. Queue size 0
released
Queue full, awaiting pop...
Gift Gift-899203208-33 has been added to the queue. Queue size: 1
GIFTS: 403
Gift Gift--948848140-41 has been added to the queue. Queue size: 2
GIFTS: 404
Gift Gift--389884399-19 has been added to the queue. Queue size: 3
GIFTS: 405
Gift Gift-615746031-32 has been added to the queue. Queue size: 4
GIFTS: 406
Gift Gift-1784101203-3 has been added to the queue. Queue size: 5
GIFTS: 407
Gift Gift--1790412473-6 has been added to the queue. Queue size: 6
GIFTS: 408

0 个答案:

没有答案