在线程之间共享一个变量?

时间:2010-10-21 08:03:04

标签: java multithreading synchronization locking

我有这种情况:

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

这就是我得到的:

关闭制作人

这里:假

完成所有

这意味着消费者仍在工作,变量“continuer”不会更新。

我也看到了thisthis帖子,我试过了,但没有任何改变。

我的问题是什么?

编辑:我改变了我的代码,显然消费者在尝试从waiting if no elements are present on this queue. 读取数据时被阻止(BlockingQueue)(参见consume(queue.take()); in消费者类)。

3 个答案:

答案 0 :(得分: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

关于您的修改:

  

我改变了我的代码,显然消费者在尝试从BlockingQueue读取数据时被阻止(等待)(请参阅消费者类中的consume(queue.take()); < / p>

您应该在c.setContinuer(false);consumerThread.interrupt()之后。在read方法中被阻塞的消费者线程将抛出InterruptedException(您可以忽略它),然后退出循环并正常终止。

答案 1 :(得分:0)

就像aioobe说的那样,每次设置它时都会创建一个新的布尔对象。那很糟糕。

更糟糕的是,您有生产者和消费者的离散连续变量。因此,如果将Producer的布尔值设置为false,为什么Consumer会受到影响?你的意思是说Consumer.getAndSet(false)吗?代码似乎有点复杂。

答案 2 :(得分:0)

您是否测试了

if (!p.getContinuer())

被采取?生产者的getContinuer未在您的示例中定义。 我会在

之后重新插入一个调试语句
c.setContinuer(false);

获取c.getContinuer()

的值

编辑:您应该为生产者和消费者使用一个Atomicboolean,正如其他答案所暗示的那样。