2013-06-22 7 views
0

В реальной жизни я столкнулся с интересной проблемой. Я упростил проблему здесь:Вопросы, связанные с многопользовательской версией

Дизайн двух методов A() и метода B(). Каждый метод можно рассматривать как получение атома элемента (A или B). Химическое соединение A [N] B [M] требует N атомов А и M атомов B.

Прежде чем мы найдем N атомов А и M атомов B, каждый вызов A() и B() будет заблокирован. Когда мы достигнем N атомов А и M атомов B, будут возвращены первые вызовы N A() и первые вызовы M B(). Например, если я вызываю вызовы N + 2 A() и следую вызовам M B(), будут возвращены первые вызовы N A() и все вызовы M B(). Будет заблокировано 2 A() звонка?

Как решить эту проблему? Я использую Java.

+0

Это звучит, как вам нужно использовать класс 'CountDownLatch'. Он дает вам методы 'countDown()' и 'wait()'. – Gray

+0

Это противоположность того, что нужно, нет? CountDownLatch будет блокироваться, пока его счетчик не достигнет 0. – Pragmateek

ответ

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; 
} 

The Thread.sleep только там для демонстрации возможного чередования потоков, но, конечно, "в производстве" удалить их.

Результат:

Got a A! 
Got a B! 
Got a A! 
Got a B! 
Got a B! 
+0

Спасибо за ответ, но я не думаю, что это работает. Мне нужно заблокировать первые два вызова A() и первые 3 B() вызова. Но похоже, что ваш код возвращает первые два вызова A() и первые 3 B() вызова, а остальные вызовы будут заблокированы. – CodeNoob

+0

Вы сказали «* Например, если я делаю вызовы N + 2 A() и следую вызовам MB(), возвращаются первые вызовы NA() и все вызовы MB(). Осталось бы 2 A() вызова блокируется? * «Это именно то, что делает этот код: два первых A и три первых B-прохода, остальные блокируются. Таким образом, в этом случае, как упоминалось * Gray *, вы можете использовать некоторые ** CountDownLatch **. Каков ваш реальный случай использования? – Pragmateek