【问题标题】:Issues in producer consumer by using java threads使用 java 线程的生产者消费者问题
【发布时间】:2016-02-22 05:11:39
【问题描述】:

我已经为生产者消费者问题编写了代码,其中生产者生产了 3 次商品,然后只有消费者消费了 1 次。以下代码作为要求工作正常,但主线程不会停止。我不知道为什么它不会停止,我无法捕捉。能否请任何人查看下面的代码并更正它?

public class ProducerConsumerProblem
{

    public static void main(String[] args)
    {

    ProducerConsumerStack st = new ProducerConsumerStack();
    new ProducerThread(st);
    new ConsumerThread(st);

    }
}

class ProducerConsumerStack
{
    int x;
    boolean flag = false;
    int producedCount = 0;

    public synchronized void push(int x)
    {
    if (flag)
    { // flag==true
        try
        {
        wait();
        }
        catch (Exception e)
        {
        System.out.println(e);
        }
    }
    this.x = x;
    System.out.println(x + " is produced..");
    try
    {
        Thread.sleep(250);
    }
    catch (Exception e)
    {
        System.out.println(e);
    }

    this.producedCount++;
    if (this.producedCount == 3)
    {
        this.producedCount = 0;
        this.flag = true;
        notifyAll();
    }

    }

    synchronized public void pop()
    {
    if (!flag)
    { // flag==false
        try
        {
        wait();
        }
        catch (Exception e)
        {
        System.out.println(e);
        }
    }
    System.out.println(x + " is consumed.\n");
    try
    {
        Thread.sleep(1500);
    }
    catch (Exception e)
    {
        System.out.println(e);
    }
    flag = false;
    notify();
    }
}

class ProducerThread implements Runnable
{
    ProducerConsumerStack st = null;

    ProducerThread(ProducerConsumerStack st)
    {
    this.st = st;
    Thread t1 = new Thread(this);
    t1.start();
    }

    public void run()
    {
    int a = 1;
    for (int i = 0; i < 15; i++)
    {
        st.push(a++);
    }
    }
}

class ConsumerThread implements Runnable
{
    ProducerConsumerStack st = null;

    ConsumerThread(ProducerConsumerStack st)
    {
    this.st = st;
    Thread t2 = new Thread(this);
    t2.start();
    }

    public void run()
    {
    for (int i = 0; i < 15; i++)
    {
        st.pop();
    }
    }
}

【问题讨论】:

  • 我不知道你为什么说,“主线程不会停止。”程序中的 main() 例程创建三个对象,然后退出。你真正想问的是什么?
  • P.S.,我在你的代码中发现了一个潜在的问题:它是对象的构造函数执行 new Thread(this).start(); 的地方。将this 传递给构造函数中的另一个线程可能允许新线程访问处于未初始化/未完全初始化状态的对象。
  • @james large : 请运行相同的代码,然后查看主线程是否完成。它根本不会完成。

标签: java multithreading


【解决方案1】:

@james large : 请运行相同的代码,然后查看主线程是否完成。它根本不会完成。

我在运行你的程序时做了一个小改动:我添加了一个等待主线程终止的线程,然后打印一条消息:

public class ProducerConsumerProblem
{
    static volatile Thread mainThread;
    public static void main(String[] args)
    {
        mainThread = Thread.currentThread();
        ProducerConsumerStack st = new ProducerConsumerStack();
        new ProducerThread(st);
        new ConsumerThread(st);

        new Thread(() -> {
            try {
                mainThread.join();
            } catch (Exception ex) {
                System.out.println("Aaaaaaaugh!");
            }
            System.out.println("Nighty Night!");
        }).start();

    }
}

它打印了“Nighty Night!”,证明主线程确实实际上已经死了。

没有终止的线程是消费者线程:当生产者线程调用st.push()十五次时,消费者线程只完成了对st.pop()的五次调用,在第六次调用中卡住了,等待一个永远不会发生的通知。


您可能想查看您的ProducerConsumerStack 课程。您在其名称中加上了“堆栈”,但对我来说它看起来不像堆栈。一方面,堆栈应该能够存储多个项目。你的只能存储一个。

【讨论】:

  • 您好,您能否将您的代码转换为低于 java8 版本的代码,这里您使用的是 java8 的特性 lambda 表达式,我不在 java8 中工作,我也不知道 lambda 表达式。请转换成java6。
  • @ManishKumar 在我的示例中,lambda 只是创建new Runnable 对象的一种简写方式。 Thread 构造函数的参数必须Runnable。编译器知道这一点,所以它会自动创建一个匿名类implements Runnable。而且,由于Runnable 接口只定义了一个方法run(),编译器知道lambda 的主体必须作为该方法的主体。 Lambda 和 函数式接口 起初可能看起来有点奇怪,但一旦你习惯了这个想法,它们实际上就会非常简单。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-30
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
  • 1970-01-01
  • 2013-11-10
相关资源
最近更新 更多