0

我在现实生活中面临一个有趣的问题。我将问题简化为:

设计两个方法 A() 和一个方法 B()。每种方法都可以被认为是产生一个元素原子(A 或 B)。化合物 A[N]B[M] 需要 N 个 A 原子和 M 个 B 原子。

在我们拥有 N 个 A 原子和 M 个 B 原子之前,每次调用 A() 和 B() 都会被阻塞。当我们到达 N 个 A 原子和 M 个 B 原子时,第一个 NA() 调用和第一个 MB() 调用将返回。例如,如果我进行 N+2 A() 调用并随后进行 MB() 调用,则第一个 NA() 调用和所有 MB() 调用都将返回。将有 2 个 A() 调用仍然被阻止?

我该如何解决这个问题?我正在使用 Java。

4

1 回答 1

1

您可以使用BlockingQueues

static class AtomA
{       
}

static class AtomB
{       
}

static class ChemicalCompound
{
    BlockingQueue<AtomA> as = new LinkedBlockingQueue<AtomA>();
    BlockingQueue<AtomB> bs = new LinkedBlockingQueue<AtomB>();

    public ChemicalCompound(int na, int nb)
    {
        while (na-- != 0) as.add(new AtomA());
        while (nb-- != 0) bs.add(new AtomB());
    }

    public AtomA A() throws InterruptedException
    {
        return as.take();
    }

    public AtomB B() throws InterruptedException
    {
        return bs.take();
    }
}

public static void main(String[] args) throws Exception
{       
    final ChemicalCompound cc = new ChemicalCompound(2, 3);

    Thread ta = new Thread(new Runnable(){
        @Override
        public void run()
        {
            while (true)
            {
                try
                {
                    cc.A();
                    System.out.println("Got a A!");
                    Thread.sleep(100);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }           
    });
    ta.start();

    Thread tb = new Thread(new Runnable(){
        @Override
        public void run()
        {
            while (true)
            {
                try
                {
                    cc.B();
                    System.out.println("Got a B!");
                    Thread.sleep(100);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }           
    });
    tb.start();

    ta.join();
    tb.join();

    return;
}

Thread.sleep只是用于演示线程的可能交错,但当然“在生产中”会删除它们。

结果:

Got a A!
Got a B!
Got a A!
Got a B!
Got a B!
于 2013-06-22T17:20:03.680 回答