6

I have a multi-threaded Java application that will output information about a message it receives to the console for debugging purposes. Each time the application receives a message, it will call a System.out.println(String) on the message.

The problem that I am having is that if the application gets flooded with messages, System.out.println() prints erroneous information (like old buffer information). This is leading me to wonder if there is a threading issue where multiple threads are calling the println function at one time, and not properly flushing the buffer.

In my main program (thread), I have something to the effect of:

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();
}

In my thread, I have something to the effect of:

@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.
}

Is there a simple way for me to have multiple threads print out to the console at one time without the buffers containing old information?

Thanks

EDIT: updated the code in the main thread to be more representative of what my program is doing.

4

4 に答える 4

2
synchronized (System.out) {
    System.out.println(message);
    System.out.flush();
}
于 2012-02-27T15:42:04.803 に答える
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 の) イベント キューでした。これは、いつ実行すべきかについての私の見解を共有していませんでした。OS がメッセージの実行方法について私とはかなり異なる考えを持っていたため、メッセージがスクランブルされていることを理解するのにしばらく時間がかかりました。

System.out.println と flush には、私が知らない微妙な点がいくつかあるかもしれませんが、すべてが機能するようになったとしても、それらのスレッドにはそれぞれ反対の考えがあることに注意してください。Logger でさえ、すべての問題を解決できるわけではありません。

于 2012-02-27T16:31:21.910 に答える
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 に答える