Java线程生成器和消费者程序问题

时间:2016-11-25 07:32:25

标签: java multithreading synchronization thread-sleep java-threads

我正在尝试Java线程生产者和消费者计划。 但消费者线程总是进入等待状态。

我无法调试消费者线程总是进入等待状态或生产者不通知消费者线程的问题

请帮我解决这个问题。这些计划如下。

communicator类调用生产者和消费者类

public class Communicator {

   Thread t = null;
    Thread t1 = null;

    public void runThread() {
        Producer p = new Producer();
        Consumer c = new Consumer(p);
        t = new Thread(p);
        t1 = new Thread(c);
        t.start();
        t1.start();
        Thread tr = new Thread() {
            public void run() {
                for (int i = 0; i < 30; i++) {
                    System.out.println("t::::::::::::: " + t.getState());
                    System.out.println("t1::::::::::::: " + t1.getState());
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException ie) {
                        ie.printStackTrace();
                    }
                }
            }
        };
        tr.start();
    }

    public static void main(String[] args) {
        Communicator c = new Communicator();
        c.runThread();
    }
}

这是生产者类,它将数据附加到stringbuffer中并通知消费者类

public class Producer extends Thread {
        public StringBuffer sb;

        public Producer() {
            sb = new StringBuffer();
        }

        public void run() {
            synchronized (sb) {
                try {
                    System.out.println("Bala");
                    sb.append("murugan");
                    sb.notify();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

以下是消费者类代码。它等待从生产者类获得通知。

public class Consumer extends Thread {
    public Producer p;

    public Consumer(Producer p) {
        this.p = p;

    }

    public void run(){
        synchronized (p.sb) {
            try {

                p.sb.wait();

            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(p.sb);
        }
    }


}

4 个答案:

答案 0 :(得分:0)

Producer已经终止,并且在notify()调用Consumer之前已经调用了wait()

ProducerConsumer extends Thread以来,请将Communicator类更新为:

public class Communicator {
    public void runThread() {
        final Producer p = new Producer();
        final Consumer c = new Consumer(p);

        p.start();
        c.start();

        Thread tr = new Thread() {
            public void run() {
                for (int i = 0; i < 30; i++) {
                    System.out.println("t::::::::::::: " + p.getState());
                    System.out.println("t1::::::::::::: " + c.getState());
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException ie) {
                        ie.printStackTrace();
                    }
                }
            }
        };
        tr.start();
    }

    public static void main(String[] args) {
        Communicator c = new Communicator();
        c.runThread();
    }
}

如果Producer尚未终止[if (p.getState() != Thread.State.TERMINATED)],那就是Consumer等待的唯一时间:

public class Consumer extends Thread {
    public Producer p;

    public Consumer(Producer p) {
        this.p = p;

    }

    public void run() {
        synchronized (p.sb) {
            try {

                if (p.getState() != Thread.State.TERMINATED) {
                    p.sb.wait();
                }

            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(p.sb);
        }

    }
}

答案 1 :(得分:0)

当前代码中几乎没有问题,其中Consumer线程始终处于等待状态,而生产者已经终止。

此外,您的StringBuffer对象需要为volatile ,以便生产者线程写入将被刷新&amp;可用于其他主题。

除此之外,我还修改了您的ProducerConsumer代码,使其更加真实(在while循环中运行,生成一些数据,另一个生成一些数据)如下图所示:(我还加入了1秒的睡眠时间以较慢的速度运行,以便您能更好地理解事物):

消费者类:

public class Producer extends Thread {
        public volatile StringBuffer sb;

        public Producer() {
            sb = new StringBuffer();
            sb.append("");
        }

        public void run() {
            synchronized (sb) {
                try {
                    while(true) {
                        Thread.sleep(1000);
                        if(sb.toString().equals("")) {
                            sb.append("murugan");
                            System.out.println(" producing sb completed *** ");
                            sb.notify();
                        } else {
                            sb.wait();
                        }
                    } 
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

消费者类:

public class Consumer extends Thread {
        public Producer p;

        public Consumer(Producer p) {
            this.p = p;

        }

        public void run(){
            synchronized (p.sb) {
                try {
                    while(true) {
                        Thread.sleep(1000);
                        if(p.sb.toString().equals("")) {
                          p.sb.wait();
                        } else {
                            String str = p.sb.toString();
                            System.out.println(" consuming sb completed **** "+str);
                            p.sb.replace(0, str.length(), "");
                            p.sb.notify();
                        }
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(p.sb);
            }
        }
    }

答案 2 :(得分:0)

对于您的问题,&#34;我无法调试消费者线程始终进入等待状态或生产者未通知消费者线程&#34;的问题。 实际上,您的消费者并不总是处于等待状态。 您可以在p.sb.wait()之前放置Thread.sleep(1000);在你的Consumer类中,你可以看到&#34; consumerThread ::::::::::::: RUNNABLE&#34;一次。    恕我直言,您的消费者代码运行得太快而无法获得等待状态,因此您错过了可运行状态。您可以从其他答案中了解更多信息。

答案 3 :(得分:0)

根据您的代码,Consumer Thread会等待Producernotify关于StringBuffer中附加的字符串。

  1. 如果Producer主题有机会获得shared StringBuffer object上的锁定(它进入synchronized block ),则Consumer Thread将进入Blocked state {1}}(将无法输入synchronized block ),因为它也是Lock的竞争者(两者都争夺获取同一共享对象的锁定)。
  2. 生产者线程完成其执行,离开synchronized block并获得终止。 请注意,通知代码不会产生任何影响,因为消费者线程尚未等待共享对象,因为尚未进入同步块
  3. Consumer thread有机会获得lock并输入synchronized blockwaits以获取有关共享对象的通知。但是,由于制作人已经终止,没有人将通知发送给Consumer thread,并且它仍处于Waiting州。
  4. 修复:在您的情况下,您可以简单地确保首先启动Consumer thread并在生产者线程之前获取锁定。为此,您可以在启动Consumer线程后让主线程休眠一段时间。

    t = new Thread(p);
    t1 = new Thread(c);
    t1.start();
    try {
            Thread.sleep(1000);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    t.start();
    

    关键点:如果您只有2个主题,则一个主题应调用notifywait。其他线程一旦被通知,只有竞争Lock的线程将获得锁定并完成其工作。完成其工作后,它应该调用notify并等待另一个线程完成工作并在完成后发出通知。这样,两个线程都将有机会一个接一个地完成工作。