Strange effect with PipedOutputStream/PipedInputStream

H

Henning Moll

Hi!

This is not the usual 'why gets my thread blocked' problem. So please
read on... ;-)

In fact, it's the other way round: The thread is not blocked.
A short example:

---snip---
import java.io.*;

public class TTT
{
public static void main(String[] args) throws IOException
{
PipedInputStream pis = new PipedInputStream();
final PrintStream pipe_start = new PrintStream(
new PipedOutputStream(pis));


Thread t = new Thread() {
public void run()
{
for(int i = 0 ; i < 100000 ; i++ )
{
pipe_start.println(i);
System.out.println(i); //Just to have some feedback
}
pipe_start.close();
System.out.println("thread finished...");
}
};

t.start();

/*This is the problem: Only one byte gets read, but
*the thread t gets never blocked. Why?
*If you comment out the following line, thread t
*gets blocked after some loops
*/
pis.read();

System.out.println("main finished");
}
}
---snip---

I allready figured out a part of the problem: Thread t is not blocked
because the main thread is finish. If you put something like

while(t.isAlive()) { }

just before 'main finished', thread t gets blocked again.
Now, how can thread t write to the pipe while the other 'end' of the
pipe is not alive anymore? There is no exception thrown (broken pipe
or similar)
And apart of that: The pipe-buffer should also be filled up to the
limit. Why is thread t not blocked?

confused
Henning
 
G

Gordon Beaton

I allready figured out a part of the problem: Thread t is not
blocked because the main thread is finish. If you put something like

while(t.isAlive()) { }

just before 'main finished', thread t gets blocked again.

And you waste a lot of cpu while this loop spins.

Try this instead:

t.join();

/gordon
 
J

John C. Bollinger

Henning said:
Hi!

This is not the usual 'why gets my thread blocked' problem. So please
read on... ;-)

In fact, it's the other way round: The thread is not blocked.
A short example:

---snip---
import java.io.*;

public class TTT
{
public static void main(String[] args) throws IOException
{
PipedInputStream pis = new PipedInputStream();
final PrintStream pipe_start = new PrintStream(
new PipedOutputStream(pis));


Thread t = new Thread() {
public void run()
{
for(int i = 0 ; i < 100000 ; i++ )
{
pipe_start.println(i);
System.out.println(i); //Just to have some feedback
}
pipe_start.close();
System.out.println("thread finished...");
}
};

t.start();

/*This is the problem: Only one byte gets read, but
*the thread t gets never blocked. Why?
*If you comment out the following line, thread t
*gets blocked after some loops
*/
pis.read();

System.out.println("main finished");
}
}
---snip---

I allready figured out a part of the problem: Thread t is not blocked
because the main thread is finish. If you put something like

while(t.isAlive()) { }

just before 'main finished', thread t gets blocked again.
Now, how can thread t write to the pipe while the other 'end' of the
pipe is not alive anymore? There is no exception thrown (broken pipe
or similar)
And apart of that: The pipe-buffer should also be filled up to the
limit. Why is thread t not blocked?

Reading is happening in the main thread; writing is happening in thread
t. According to the API docs for PipedOutputStream.write(byte), "If a
thread was reading data bytes from the connected piped input stream, but
the thread is no longer alive, then an IOException is thrown." The same
also applies to the other overridden write method. When the main thread
exits, then, t unblocks because an IOException is propagated out through
the println() invocation. The exception is not caught inside your loop,
or even inside your run() method, so the run method exits and the thread
dies.

There is some room to question what happens if t is already blocked on a
write when the main thread dies, but the answer seems to be evident in
the observed behavior, at least with the JVM and class libraries in use.

A sometimes surprising characteristic of threads in Java is that
uncaught exceptions are only reported to the console from the main
thread, not from any other thread. Exceptions do not propogate outside
the thread in which they were raised, and that should complete the
picture for you.


John Bollinger
(e-mail address removed)
 
H

Henning Moll

John C. Bollinger said:
[...] The same
also applies to the other overridden write method. When the main thread
exits, then, t unblocks because an IOException is propagated out through
the println() invocation. The exception is not caught inside your loop,
or even inside your run() method, so the run method exits and the thread
dies.

I understand what you mean, but there is no IOException thrown. Try it!
I modifyied my thread to something like this:

....
try
{
pipe_start.println(i);
}
catch(Throwable t)
{
t.printStackTrace();
}
....

As i said: No exception
A sometimes surprising characteristic of threads in Java is that
uncaught exceptions are only reported to the console from the main
thread, not from any other thread. Exceptions do not propogate outside
the thread in which they were raised, and that should complete the
picture for you.

Yes, that's clear to me, but it is not an answer to my problem...
Any other suggestions?

Henning
 
J

John C. Bollinger

Henning said:
I understand what you mean, but there is no IOException thrown. Try it!
I modifyied my thread to something like this:

...
try
{
pipe_start.println(i);
}
catch(Throwable t)
{
t.printStackTrace();
}
...

As i said: No exception

I did try it, and as you said, there was no exception. Then I took the
PrintStream out of the picture, and used the PipedOutputStream directly:
in that case there was an exception as predicted. My best guess, then,
is that your PrintStream is either buffering the input or swallowing the
exceptions, more likely the former.


John Bollinger
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top