6

我有一个多线程 Java 应用程序,它会将有关它接收到的消息的信息输出到控制台以进行调试。应用程序每次收到消息时,都会System.out.println(String)在消息上调用一个。

我遇到的问题是,如果应用程序被消息淹没,则会System.out.println()打印错误信息(如旧缓冲区信息)。这让我想知道是否存在线程问题,即多个线程println一次调用该函数,并且没有正确刷新缓冲区。

在我的主程序(线程)中,我有一些效果:

while(iterator.hasNext())
{
    SelectionKey key = iterator.next();

    channel.receive(buffer);     // The buffer is a ByteBuffer.
    buffer.flip();

    new Thread(new ThreadToPrintTheMessage(buffer)).start();

    buffer.clear();

    iterator.remove();
}

在我的线程中,我有一些效果:

@Override
public void run()
{
    System.out.println(message);
    System.out.flush();   // I have better results with this.  But, it doesn't
                          // fully resolve the issue.
}

有没有一种简单的方法可以让多个线程一次打印到控制台,而缓冲区不包含旧信息?

谢谢

编辑:更新了主线程中的代码,以更能代表我的程序正在做什么。

4

4 回答 4

2
synchronized (System.out) {
    System.out.println(message);
    System.out.flush();
}
于 2012-02-27T15:42:04.803 回答
2

为此,您应该使用 Java.util.logging 或其他一些日志框架。

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/logging/Logger.html

import java.util.logging.Logger;
....
Logger log = Logger.getLogger("com.something.something");
....
log.log(Level.Info, "Message");
于 2012-02-27T15:47:30.690 回答
2

这里可能是一些解决问题的示例代码:

while(iterator.hasNext())
{
    SelectionKey key = iterator.next();

    channel.receive(buffer);     // The buffer is a ByteBuffer.
    buffer.flip();
    byte[] bytes = new byte[buffer.limit()];  // copy buffer contents to an array
    buffer.get(bytes);
    // thread will convert byte array to String
    new Thread(new ThreadToPrintTheMessage(bytes)).start();

    buffer.clear();

    iterator.remove();
}
于 2012-02-27T16:31:04.400 回答
2

我没有时间检查 println 源确保它始终是线程安全的(如果你愿意,你可以),但你确定你的 println 是错误的吗?很可能代码运行的时间与您想象的完全不同。线程经常挂在锁上或者只是被调度程序忘记了,所以你认为应该运行的 A、B、C、D 可以运行 B、C、D、A。然后你想知道为什么 println 搞砸了,最后打印什么你以为先跑了。这是一个非常简单的例子。您期望使用多线程发生的事情与实际发生的事情之间的差异确实令人震惊。通常,线程与内核的比率越高,情况越差。单核机器总是做与你期望相反的事情。

你甚至不需要多个线程来解决这个问题。我的第一次颠簸来自于事件队列(在 Windows 3.1 上),它并没有分享我对什么时候应该运行的看法。我花了一段时间才发现这些消息被打乱了,因为操作系统对它们应该如何运行的想法与我的想法大不相同。

System.out.println 和 flush 很可能有一些我不知道的微妙之处,但即使你得到了所有这些工作,请注意这些线程有自己的相反想法。即使是 Logger 也无法解决您的所有问题。

于 2012-02-27T16:31:21.910 回答