简体   繁体   English

使用Java中的等待/通知机制终止Producer-Consumer线程

[英]Terminating Producer-Consumer threads with wait/notify mechanism in Java

The application I'm maintaining (passed through many coders) has the Producer-Consumer problematic implemented using wait/notify mechanism. 我正在维护的应用程序(通过许多编码器)具有使用等待/通知机制实现的Producer-Consumer问题。

Consumer waits for the message on the "server" side of the application and then forwards the message on the "client" side towards the LDAP server. 使用者在应用程序的“服务器”端等待消息,然后在“客户端”端将消息转发给LDAP服务器。

Problem is when multiple connections are established/terminated. 问题是建立/终止多个连接时。 The Producer threads just keep multiplicating and never get terminated when they should. 生产者线程只是保持乘法并且永远不会终止。

When a connection is terminated both the Producer/Consumer threads should be terminated as well. 当连接终止时,两个生产者/消费者线程也应终止。 With a high number of established/terminated connections, memory usage gets monstrous. 通过大量已建立/终止的连接,内存使用情况变得异常糟糕。

The code: 编码:

class Producer extends Thread {
    public void run() {
        long previous = 0;
        long last = 0;
        long sleeptime = 1;

        while (alive) {
            try{
                last = System.currentTimeMillis();

                byte[] aux;
                if ((aux = cliente.readmessage()) != null){

                    sleeptime = 1;
                    previous = last;

                    synchronized (list) {
                        while (list.size() == MAX)
                            try {
                                list.wait();
                            } catch (InterruptedException ex) {
                            }
                        list.addFirst(new Messagetimestamped(aux, System
                                .currentTimeMillis()));
                        list.notifyAll();
                    }
                }
                else{
                    if (last-previous > 1000)
                        sleeptime = 1000;
                    else
                        sleeptime = 1;
                    sleep(sleeptime);
                }
            }
            catch (Exception e){
                if (lives()){
                    System.out.println("++++++++++++++++++ Basic Process - Producer");
                    kill();
                    nf.notify(false, processnumber);
                }
                return;
            }
        }
    }
}


class Consumer extends Thread{

    public void run() {
        while (alive) {
            byte[] message = null;
            Messagetimestamped  mt;
            synchronized(list) {
                while (list.size() == 0) {
                    try {
                        list.wait(); //HANGS HERE!
                        if (!alive) return;
                        sleep(1);
                    }
                    catch (InterruptedException ex) {}
                }
                mt = list.removeLast();
                list.notifyAll();
            }
            message = mt.mensaje;

            try{
                long timewaited = System.currentTimeMillis()-mt.timestamp;

                if (timewaited < SLEEPTIME)
                    sleep (SLEEPTIME-timewaited);

                if ( s.isClosed() || s.isOutputShutdown() ){
                    System.out.println("++++++++++++++++++++ Basic Process - Consumer - Connection closed!(HLR)");
                    kill();
                    nf.notify(false, processnumber);
                }
                else {
                    br.write(message);
                    br.flush();
                }
            } catch(SocketException e){
                return;
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

Basically after alive is set to false Producer gets actually terminated. 基本上,将live设置为false生产者实际上会终止。 Consumer doesn't. 消费者没有。 It just stays hanging on the list.wait() line. 它只是挂在list.wait()行上。 Obviously the list.notify() (or list.notifyAll() ?) from Producer isn't delivered after it's terminated so Consumer never gets to check the alive boolean. 显然, list.notify() (或list.notifyAll()生产的?)它的终止之后不传递这样消费者永远不会检查alive布尔。

How to solve this using as little modifications as possible? 如何使用尽可能少的修改来解决此问题?

Thanks. 谢谢。

I would just use an ExecutorService which will wrap up the queue, manage your thread(s) and handle shutdown for you. 我只会使用ExecutorService来包装队列,管理线程并为您处理关机。 Almost all your code will go away if you do. 如果您这样做,几乎所有代码都将消失。

But to answer your question, I suggest sending a poison pill. 但要回答您的问题,我建议您发送毒药。 A special object which the consumer will shutdown when it receives it. 特殊对象,消费者在收到它时将关闭它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM