有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程应用程序中的java可选调试输出是为客户机提供的,而不是为了找出死锁或bug

为了学习,我在做my first multi-threaded application。我真的需要学习。我已经有了一个单线程函数,可以读取目录中的所有文本文件,并将所有缩进选项卡替换为三个空格

为了获得可选的额外信息(列出每个文件、提供统计信息等),它能够传入一个^{}。如果它们传入null,则不需要调试

我试图确定在多线程版本中处理这个问题的最佳方法是什么,但搜索“调试多线程java”只会告诉我如何诊断错误和死锁

我可以安全地使用一个可附加的功能吗?还是应该考虑其他功能?我不确定如何处理交错消息,但我想弄清楚的第一件事是线程安全


共 (3) 个答案

  1. # 1 楼答案

    <>而不是在^ {}中传递,考虑在库中使用slf4j来进行日志记录。

    如果在运行时未链接任何日志框架,则不会执行任何日志记录。如果应用程序已经在做日志记录,那么slf4j可能会输出到它的前端

    我建议在日志输出中使用Logback,因为它可以通过配置文件或直接在代码中进行很好的配置。要获得基本输出,只需包含JAR

  2. # 2 楼答案

    调试线程通常是一种试图弄清楚演示文稿的情况。Log4j一般都很棒。您可以将其配置为使用线程名称和时间戳标记每一行。一旦你这样做了,你就可以根据线程名过滤输出,并跟随一个线程

    一个好的过滤工具非常重要。最基本的方法是通过grep进行跟踪和管道传输,但是如果你经常这样做的话,你可能会想在日志上添加一些东西,比如一个GUI,每个线程都有标签,或者类似的东西

    Log4j本身在处理线程方面没有问题

    如果你真的想自己做,给每个线程传递一个不同的appendable,然后在线程完成后转储它或将它保存到一个文件中。您可能只想使用一个线程来转储/保存可追加内容

  3. # 3 楼答案

    从多个线程使用Appendable的问题是,它没有被指定为线程安全的

    Thread safety is the responsibility of classes that extend and implement this interface.

    因此,答案是使用线程安全的多路复用器。这一个使用一个BlockingQueue和一个线程,从中提取数据并将其转发给他们的Appendable

    class TellThemWhatIsHappening implements Appendable {
    
        // The pipe to their system/log.
        private final Appendable them;
        // My internal queue.
        private final BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
        // Hav I been interrupted?
        private volatile boolean interrupted = false;
    
        public TellThemWhatIsHappening(Appendable them) {
            // Record the target Appendable.
            this.them = them;
            // Grow my thread.
            Thread t = new Thread(consumer);
            // Make sure it doesn't hold your app open.
            t.setDaemon(true);
            // Start the consumer runnning.
            t.start();
        }
    
        // The runnable that consumes the queue and passes it on to them.
        private Runnable consumer = new Runnable() {
    
            @Override
            public void run() {
                while (!interrupted) {
                    try {
                        // Pull from the queue and push to them.
                        them.append(queue.take());
                    } catch (InterruptedException ex) {
                        // We got interrupted.
                        interrupted = true;
                    } catch (IOException ex) {
                        // Not sure what you shoudl do here. Their appendable threw youy an exception.
                        interrupted = true;
                    }
                }
            }
    
        };
    

    继续

        private void append(String s) throws IOException {
            // No point if they are null.
            if (them != null) {
                try {
                    queue.put(s);
                } catch (InterruptedException ex) {
                    // What should we do here?
                    interrupted = true;
                }
            }
        }
    
        @Override
        public Appendable append(CharSequence csq) throws IOException {
            append(csq.toString());
            return this;
        }
    
        @Override
        public Appendable append(CharSequence csq, int start, int end) throws IOException {
            append(csq.subSequence(start, end).toString());
            return this;
        }
    
        @Override
        public Appendable append(char c) throws IOException {
            append("" + c);
            return this;
        }
    
    }
    

    然而,使用一个合适的日志系统进行日志记录是一个非常好的主意,而不是自己开发