2010-10-21 5 views
1

у меня есть такой сценарий:Поделитесь одной переменной между потоками?

class MyClass { 
    Producer p; 
    Consumer c; 
    public static void main(String[] args){ 
     BlockingQueue q = new LinkedBlockingQueue(); 
     p = new Producer(q); 
     c = new Consumer(q); 
     Thread t = new Thread(p); 
     t.start(); 
     new Thread(c).start(); 
     while (true) { 
      if (!p.getContinuer()) { 
       c.setContinuer(false); 
       System.out.println("here:"+p.getContinuer().toString()); 
       break; 
      } 
     } 
     System.out.println("finish all"); 
    } 
} 

class Producer implements Runnable { 
private final BlockingQueue queue; 
private AtomicBoolean continuer = new AtomicBoolean(true); 
    public Boolean getContinuer() { 
     return continuer.get(); 
    } 
    @Override 
    public void run() { 
     while(true){ 
     //open socket 
     //read data from socket 
     queue.put(data); 
     if(end){ 
      System.out.println("Shutting down Producer"); 
      continuer.getAndSet(false); 
     } 
     } 
    } 
} 

class Consumer implements Runnable { 
    private final BlockingQueue queue; 
    private static AtomicBoolean continuer = new AtomicBoolean(true); 

    public void setContinuer(Boolean continuerr) { 
     continuer = new AtomicBoolean(continuerr); 
    } 

    public Boolean getContinuer() { 
     return continuer.get(); 
    } 

    @Override 
    public void run() { 
      while (getContinuer()) { 
      //Do some work 
      consume(queue.take()); 
      } 
      System.out.println("shut down Consumer"); 
    } 
} 

это то, что я получаю:

Выключение Производитель

здесь: ложные

закончить все

, что означает, что потребитель все еще работает, а переменная «продолжатель» не обновляется.

Я видел также this и this сообщений, я попробовал, но ничего не изменилось.

В чем моя проблема?

EDIT: я изменил код, и, видимо, потребитель заблокирован (waiting if no elements are present on this queue.) при попытке чтения данных из BlockingQueue (см потреблять (queue.take()); в классе потребителей).

+0

Этот код не компилируется. – aioobe

+1

@aioobe - это было бы проблемой :) – willcodejavaforfood

+0

нет, мой код компилируется (это всего лишь образец моего кода, поэтому, возможно, есть некоторая ошибка). – mohamida

ответ

3

Ну

public void setContinuer(Boolean continuerr) { 
    continuer = new AtomicBoolean(continuerr); 
} 

кажется неправильным. Почему вы не

public void setContinuer(boolean continuerr) { 
    continuer.set(continuerr); 
} 

Кроме того, если переменная end не летучий, может кэшировать в потоках.


Нам нужно будет увидеть больше кода. (Или, по крайней мере, компиляции кода.) Так как этот код работает, как ожидалось:

import java.util.concurrent.*; 

public class MyClass { 
    static Producer p; 
    static Consumer c; 

    public static void main(String[] args) { 
     BlockingQueue q = new LinkedBlockingQueue(); 
     p = new Producer(); 
     c = new Consumer(); 
     Thread t = new Thread(p); 
     t.start(); 
     new Thread(c).start(); 
     while (true) { 
      if (!p.getContinuer()) { 
       c.setContinuer(false); 
       break; 
      } 
     } 
     System.out.println("finish all"); 
    } 
} 

class Producer implements Runnable { 
    private boolean end = true; 
    private BlockingQueue queue; 
    private AtomicBoolean continuer = new AtomicBoolean(true); 

    public boolean getContinuer() { 
     return continuer.get(); 
    } 

    @Override 
    public void run() { 
     while (true) { 
      // open socket 
      // read data from socket 
      if (end) { 
       System.out.println("Shutting down Producer"); 
       continuer.getAndSet(false); 
       break; 
      } 
     } 
    } 
} 

class Consumer implements Runnable { 
    private BlockingQueue queue; 
    private static AtomicBoolean continuer = new AtomicBoolean(true); 

    public void setContinuer(Boolean continuerr) { 
     continuer = new AtomicBoolean(continuerr); 
    } 

    public Boolean getContinuer() { 
     return continuer.get(); 
    } 

    @Override 
    public void run() { 
     while (getContinuer()) { 
      // Do some work 
     } 
     System.out.println("shut down Consumer"); 
    } 
} 

Он печатает

Shutting down Producer 
finish all 
shut down Consumer 

Что касается вашего редактирования:

я изменил мой кода, и, по-видимому, потребитель блокируется (ждет) при попытке чтения данных из Blo ckingQueue (см.потребление (queue.take()); в потребительском классе).

Вы должны, после c.setContinuer(false); сделать consumerThread.interrupt(). Потребительский поток, который заблокирован в методе read, будет вызывать InterruptedException (который вы можете игнорировать), а затем выйти из цикла и закончить.

+0

Благодарю вас за ответ, но это не сработало. И нет, конец не кэшируется, потому что вы можете видеть, что поток заканчивает свою работу в MyClass и Producer. – mohamida

+0

извините, но я нашел проблему (я изменил сообщение). – mohamida

+0

Обновлен мой ответ. – aioobe

0

Как сказал aioobe, вы создаете новый объект типа boolean каждый раз, когда вы его устанавливаете. Плохо.

Хуже того, у вас есть дискретные переменные продолжения для Продюсера и Потребителя. Итак, если вы установите логическое значение Producer на false, почему потребитель должен быть затронут? Вы хотите сказать Consumer.getAndSet(false)? Код кажется немного запутанным.

+0

Посмотрите на его цикл while в основной теме. – aioobe

+0

У меня есть эта строка «c.setContinuer (false);» in MyClass – mohamida

+0

Oh goodness ... – EboMike

0

испытания Вы беретесь ли

if (!p.getContinuer()) 

? getContinuer для производителя не определен в вашем примере. я recoment вставить отладки заявление после

c.setContinuer(false); 

, чтобы получить значение c.getContinuer()

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

+0

Извините, я забыл (я изменил код). c.getContinuer() содержит false (я также изменил свои отпечатки). И, как вы можете видеть в моем коде, я уже использую AtomicBoolean. – mohamida

Смежные вопросы