线程组在调用中断后离开僵尸线程

时间:2018-12-02 21:26:07

标签: java multithreading synchronization interrupt

我有一个主管线程和几个工作线程。让我们假设我们有精灵来包装礼物并将其发送到工厂,然后将它们排入队列。送完一定数量的礼物后,主管告诉工作停止。

我所有的工作线程都属于一个线程组。当主管意识到已经达到所需的礼物数量时,它将调用workerThreadGroup.interrupt()。但是,总会有僵尸工人继续生产。

现在,输入一些代码:

public class Factory implements Runnable {

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

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


        }


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

    }


    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(elvesThreadGroup, elfRunnable);
        }
    }

    private synchronized void queryPositions() {
        try {
            positionQuerySemaphore.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 {
            positionQuerySemaphore.release();
        }

    }


    public synchronized void notifyGiftCreated(Gift gift) {
        if (producedGifts == maxGifts) {
            elvesThreadGroup.interrupt();
            goalNotAchieved = false;
            orchestrator.setWorkersTurn();
            System.out.println("Rejecting " + gift);

        } else {
            producedGifts++;
            System.out.println("GIFTS: " + producedGifts);
        }


    }

}


public class ElfRunnable implements Runnable {

    @Override
    public void run() {
        notifySupervisorFactory();
        while (threadIsAlive()) {

            orchestrator.awaitWorkersTurn();
            if (elfPosition.randomMove()) {
                Gift gift = new Gift(random.nextInt(), ID);
                orchestrator.setSuperVisorTurn();
                supervisorFactory.notifyGiftCreated(gift);
                rest();
            } else {
                awaitRandom();
            }


        }
        System.out.println("Elf " + ID + "/" + supervisorFactory + " is DONE");
    }

    private boolean threadIsAlive() {
        return !Thread.currentThread().isInterrupted();
    }


    private void notifySupervisorFactory() {
        supervisorFactory.becomeAware(this);
    }

    private void rest() {
        try {
            Thread.sleep(30);
        } catch (InterruptedException ignored) {
        }

    }

    private void awaitRandom() {

        int minimum = 10;
        int maximum = 50;
        int waitingTime = random.nextInt(maximum - minimum) + minimum;
        try {
            Thread.sleep(waitingTime);
        } catch (InterruptedException ignored) {
        }
    }


}


public class Orchestrator implements IDefinitions {
    private volatile int turn;

    public Orchestrator(int turn) {
        this.turn = turn;
    }

    public synchronized void awaitWorkersTurn() {
        while (turn == supervisorTurn) {
            try {
                wait();
            } catch (InterruptedException ignored) {
                return;
            }
        }
    }

    public synchronized void awaitSupervisorTurn() {
        while (turn == workerTurn ) {
            try {
                wait();
            } catch (InterruptedException ignored) {
                return;
            }
        }

    }

    public synchronized void setWorkersTurn() {
        turn = workerTurn;
        notifyAll();
    }

    public synchronized void setSuperVisorTurn() {
        turn = supervisorTurn;
        notifyAll();
    }



}

现在,我在输出过程中得到了什么:

Factory 0 got: 20 toys to produce, 347 as matrix size, 5 elves
Thread elf 0/0 group: java.lang.ThreadGroup[name=main,maxpri=10]
Thread elf 1/0 group: java.lang.ThreadGroup[name=main,maxpri=10]
Thread elf 2/0 group: java.lang.ThreadGroup[name=main,maxpri=10]
Thread elf 3/0 group: java.lang.ThreadGroup[name=main,maxpri=10]
Thread elf 4/0 group: java.lang.ThreadGroup[name=main,maxpri=10]
Factory 0 is working..
Elf 1 created a gift
Elf 3 created a gift
Elf 0 created a gift
Elf 4 created a gift
Elf 2 created a gift
Factory 0 is working..
GIFTS: 1
GIFTS: 2
GIFTS: 3
GIFTS: 4
GIFTS: 5
Elf 4 created a gift
Elf 2 created a gift
Elf 3 created a gift
Factory 0 is working..
GIFTS: 6
Elf 1 created a gift
Elf 0 created a gift
Factory 0 is working..
GIFTS: 7
GIFTS: 8
GIFTS: 9
GIFTS: 10
Elf 2 created a gift
GIFTS: 11
Elf 0 created a gift
GIFTS: 12
Elf 4 created a gift
Elf 3 created a gift
Factory 0 is working..
Elf 1 created a gift
GIFTS: 13
Factory 0 is working..
GIFTS: 14
GIFTS: 15
Elf 2 created a gift
Elf 4 created a gift
Elf 0 created a gift
Factory 0 is working..
GIFTS: 16
GIFTS: 17
GIFTS: 18
Elf 1 created a gift
Elf 3 created a gift
GIFTS: 19
Factory 0 is working..
GIFTS: 20
Elf 4 created a gift
Elf 0 created a gift
Elf 2 created a gift
Rejecting Gift--820046672-4
Factory 0 is working..
Elf 4/0 is DONE
Elf 1 created a gift
Elf 3 created a gift
----------------Factory 0 FINISHED----------------
Rejecting Gift-1775300653-2
Rejecting Gift--906406470-0
Elf 2/0 is DONE
Rejecting Gift--778562716-3
Elf 0/0 is DONE
Elf 3/0 is DONE
Rejecting Gift-912276334-1
Elf 1 created a gift
Rejecting Gift--203717575-1
Elf 1 created a gift
Rejecting Gift--504209300-1
Elf 1 created a gift
Rejecting Gift--1405618643-1
Elf 1 created a gift
Rejecting Gift-472265871-1
Elf 1 created a gift
Rejecting Gift-1573561986-1
Elf 1 created a gift
Rejecting Gift-2005222080-1
Elf 1 created a gift
Rejecting Gift-1722629349-1
Elf 1 created a gift
Rejecting Gift-678251744-1
Elf 1 created a gift
Rejecting Gift--1911462918-1
Elf 1 created a gift
Rejecting Gift-994905496-1
Elf 1 created a gift
Rejecting Gift--1700057698-1
Elf 1 created a gift
Rejecting Gift-2040969141-1
Elf 1 created a gift
Rejecting Gift--135605836-1
Elf 1 created a gift
Rejecting Gift--1320452586-1

如您所见,总是有一个僵尸线程在运行。为什么会这样?

1 个答案:

答案 0 :(得分:1)

您的代码的问题是您想使用interupt()方法取消/停止您的工作线程,但是同时您正在线程上调用方法,如果该线程已经被中断,则该方法将引发被中断的异常。这将清除中断状态。

举个例子,您的代码中可能会发生什么:

您的精灵运行方法周期:

while (threadIsAlive()) {

1)           //dostuff -> while you are doing the stuff, supervisor call threadGroup.interrupt()
2)           awaitRandom();
}

1)在执行doStuff代码期间,主管调用 threadGroup.interrupt(),这将设置线程的中断状态,如果调用Thread.currentThread.isInterrupted(),您将得到true < / p>

2)在这里,您正在调用sleep()方法,如果sleep方法已在已中断的线程上调用,则sleep方法将引发 InterruptedException ,并将清除中断状态! 检查javadoc:https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#sleep(long) 因此,如果您调用 threadIsAlive(),则方法 Thread.currentThread.isInterrupted()将返回false。

所以您可以做的是,可以在awaitRandom()(以及其他所有引发InterruptedExceptions并清除中断状态的方法中)捕获interrputedException,然后再次设置中断状态,如下所示:

 try {
            Thread.sleep(waitingTime);
        } catch (InterruptedException ex) {
    Thread.currentThread().interrupt(); //restores the interrupt status
}

但是更好的选择是通过其他机制取消/停止线程,而不是使用中断标志。您可以在工作线程中引入一些新的volatile标志停止变量(类似于对targetNotAchieved所做的操作),如果要取消/停止线程,则可以设置此变量。

相关问题