0

私は実生活で興味深い問題に直面しています。ここに問題を単純化しました。

2 つのメソッド 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 に答える