I was working on Threads and decided to add some extra text before and after my focused lines of code are run, for reference. I expected to get one 'extra-text' towards the start and the other at the end. However... that's not happening and the second 'extra-text' just comes at the fourth position when I run it. I am a beginner and need to know why this is happening...
---CODE---
class Hi extends Thread{
public void run(){
for(int i=1; i<=5; i++){
System.out.println("HI!");
try{
Thread.sleep(500);
} catch(InterruptedException e){}
}
}
}
class Hey extends Thread{
public void run(){
for(int i=1; i<=5; i++){
System.out.println("HEY!");
try{
Thread.sleep(500);
} catch(InterruptedException e){}
}
}
}
public class MyClass {
public static void main(String[] args){
Hi hiObj = new Hi();
Hey heyObj = new Hey();
System.out.println("extra-text");
hiObj.start();
heyObj.start();
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("extra-text");
}
}
---OUTPUT---
extra-text
HI!
HEY!
extra-text
HEY!
HI!
HEY!
HI!
HEY!
HI!
HEY!
HI!
This is a common concurrency error.
The main method of your program runs on the main thread. Thus, before you've started the hiObj and heyObj threads, you already have one thread. After you start both of the new threads, you have three. Each executes concurrently. This means that each thread can execute code without waiting for the others. Order is not guaranteed between threads.
This causes the behavior you observe. Before hiObj or heyObj are started, the main method running on the main thread prints "extra-text". Next, hiObj and heyObj are started. The main thread reaches the line Thread.currentThead().sleep(10) which causes it to suspend execution for 10 milliseconds. On most machines (including yours), this is enough time for the other two threads to begin execution. Each thread begins the for loop in its run method and prints either "HI" or"HEY". Thus, the first three lines of output are (the order of "HI" and "HEY" are not guaranteed):
"extra-text"
"HI"
"HEY"
Next, the hiObj and heyObj threads reach the line Thread.sleep(500) which causes them to suspend execution for 500 milliseconds. After 10 milliseconds have passed, the main thread will be finished sleeping a will resume. Note that neither the hiObj or heyObj threads could have resumed by now. Thus, the next line printed will be the from the next line executed in main. This is "extra-text". Thus, the expected output is:
"extra-text"
"HI"
"HEY"
"extra-text"
Over the next few seconds, the remaining prints from the hiObj and heyObj threads will occur. In Java, the main thread exits only after all other threads have exited (unless System.exit is called or there is an uncaught exception). In this case this means the program will only exit when main reaches the end of execution and when both hiObj's and heyObj's run methods return.
To change your program so that the last "extra-text" always prints at the end, you have to cause the main thread to wait for the hiObj and heyObj threads to finish. In Java, there is a method on Thead called join which causes the calling thread to wait until the joined thread dies. In your program, you can modify MyClass to look like this:
public class MyClass {
public static void main(String[] args){
Hi hiObj = new Hi();
Hey heyObj = new Hey();
System.out.println("extra-text");
hiObj.start();
heyObj.start();
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
hiObj.join();
heyObj.join();
System.out.println("extra-text");
}
}
With this change, main will first wait for hiObj to finish and then wait for heyObj to finish before it prints "extra-text".
If you get rid of the
Thread.currentThread().sleep(10);
in the main Method you will see that your two extra texts are printed to the console immediately after execution. By using the sleep(10) you just delay the second extra text and in the meantime your 2 threads print their first output.
Related
public class oneThread extends Thread {
public void run()
{
System.out.println("geeks ");
try {
Thread.sleep(300);
}
catch (InterruptedException ie) {
}
System.out.println("forgeeks ");
}
public static void main(String[] args)
{
oneThread c1 = new oneThread();
oneThread c2 = new oneThread();
c1.start();
c2.start();
System.out.println(c1.isAlive());
System.out.println(c2.isAlive());
}
}
its real output is ->
geeks
true
true
geeks
forgeeks
forgeeks
how is this correct ?
I expected it to be ->
geeks
geeks
true
true
forgeeks
forgeeks
There are lots of legal execution sequences that could give rise to that output.
For example:
in main: c1.start()
in main: c2.start()
in thread 1: println("geeks")
in thread 1: sleep
in main: println(c1.isAlive()); println(c2.isAlive());
in thread 2: println("geeks")
in thread 2: sleep
in thread 1: println("for geeks")
in thread 2: println("for geeks")
JVM terminates since all threads have completed
Other possible execution sequences include:
Steps 3 and 4 could happen before step 2.
Thread 2 could be scheduled before thread 1.
Thread 2 could "overtake" thread 1 due to the sleep times being imprecise.
And so on.
These are all legal behaviors, and on some platforms you might actually encounter them.
This is perfectly valid behavior. The JVM is free to decide which Thread runs and when. Some of the things you should note is that starting a thread takes some time, and while Thread 2 is still starting, main keeps going and gets to its print. Also Threads can be put to sleep for a lengthy IO operation such as System.out.println, and another thread will run while the print is executing.
In this code segment, I create a pipe and attach a Scanner on one end and a PrintStream on the other in order to communicate between several consumer and producer threads. Then I create and start three threads:
The first thread is a consumer thread. It checks the Scanner to see if a line of text is available to consume, consumes it, prints to stdout and then sleeps for a few milliseconds and then repeats. If there's nothing to consume, then it prints a message about that, sleeps and repeats.
The second thread in this code segment does nothing. More on that below.
2.5 There's a 3 second delay before the 3rd thread launches.
The third thread is a producer and just produces text messages for the first thread to consume. It produces a message, sleeps
public static void main(String[] args) throws IOException
{
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
Scanner scan = new Scanner(pis);
PrintStream ps = new PrintStream(pos);
new Thread()
{
public void run()
{
int x = 0;
while (true)
{
x++;
if (scan.hasNextLine())
{
System.out.println("pulled: " + scan.nextLine());
} else
{
if (x % 100 == 0)
{
System.out.println("no data to pull");
}
}
try
{
sleep(10);
} catch (InterruptedException ex) { }
}
}
}.start();
new Thread()
{
public void run()
{
}
}.start();
try
{
sleep(3000);
} catch (InterruptedException ex) { }
new Thread()
{
public void run()
{
int x = 0;
while (true)
{
x++;
ps.println("hello: " + x);
try
{
sleep(1000);
} catch (InterruptedException ex) {}
}
}
}.start();
}
The output (as I expect):
pulled: hello: 1
pulled: hello: 2
pulled: hello: 3
pulled: hello: 4
pulled: hello: 5
pulled: hello: 6
Also note that the scan.nextLine() is blocking (since there are no messages indicating that no data was available... data is always "available" even if it's "on the way").
Now, if I replace the body of the 2nd thread with some code that produces some text for the first thread to consume:
new Thread()
{
public void run()
{
ps.println( "Interfere");
}
}.start();
Then I start to trigger the no data clause of the first thread:
pulled: Interfere
no data to pull
no data to pull
no data to pull
no data to pull
no data to pull
no data to pull
no data to pull
no data to pull
So if the second thread starts using the PrintStream object to produce messages, something goes wrong in the pipe and the consumer thread stops being able to find messages on the other end.
And now things get weirder. If I prevent the second thread from finishing, say by throwing it into a really long loop, then the pipe doesn't get gummed up:
new Thread()
{
public void run()
{
ps.println("interfere");
for ( long i = 0; i < 10000000000L; i++ );
System.out.println("done interfering" );
}
}.start();
Output:
pulled: interfere
pulled: hello: 1
pulled: hello: 2
done interfering
pulled: hello: 3
pulled: hello: 4
pulled: hello: 5
pulled: hello: 6
So I think that if the second thread terminates before the third thread starts producing, then the first thread won't ever get any messages from the third thread. However, if the the second thread manages to hang on until the third thread starts producing then everything goes through as expected.
What's going on here? Is the second thread closing the pipe/stream (or performing some other action on the pipe/stream) when it terminates? If so, why? And why does it not seem to close (or perform whatever action on) the pipe/stream if the third thread starts using the pipe/stream before the second thread terminates? Is there a way to make this code "work" as expected (that is so that the first thread consumes whatever is produced by either/both producer threads) when the second thread produces messages and terminates before the third thread starts?
Background:
This is a condensing to essential components of a system in which several clients will consume messages from a single producer thread. However, the producer thread can't be started until all client threads have signaled that they are ready. For each client thread, there's another thread which queries if they are ready. Once all the client threads have signaled that they are ready, the producer thread is launched. I'm trying to have the threads communicate via streams so that later I can distribute them over several computers and set up the pipes using sockets with a minimal amount of change to the underlying code. Feel free to suggest an alternate solution strategy here as well, but I'd like to understand why the solution above doesn't work.
Your Scanner instance is hitting an exception in its readInput method which sets its sourceClosed field to true and prevents you from reading. If you're interested in where it actually happens:
private void readInput() {
...
int n = 0;
try {
n = source.read(buf);
} catch (IOException ioe) {
lastException = ioe;
n = -1;
}
if (n == -1) {
sourceClosed = true;
needInput = false;
}
...
}
This behavior isn't wrong, you need to fix the underlying exception. The issue here is a java.io.IOException: Write end dead. There are a bunch of answers and blog posts that can help you address this better than I can. Also take a look at the related "Read end dead" issue. Check out:
https://techtavern.wordpress.com/2008/07/16/whats-this-ioexception-write-end-dead/
IO Exception - read end dead - what causes it in this example and how to fix it - multithread application in Java
Write end dead exception using PipedInputStream java
The stream objects involved are not thread safe, so the behavior when accessing them from different threads without synchronization is unpredictable. I would guess that in this particular case, the difference in behavior has to do with what actually gets flushed to main memory, but that's just a guess.
To get predictable behavior, you need to do proper synchronization between your threads.
The following snippet is a thread named "Foo" that sleeps for 1 minute and then copies the data typed in 1 minute to a log file.
while(isStarted) {
try {
Thread.sleep(60000); // sleep for 1 minute
ArrayList<String> keyStrokeList = nativeMethods.getKeyStrokeList();
int result = copy.copyToLogFile(keyStrokeList);
System.out.println(result);
} catch(Exception exc) {
exc.printStackTrace();
}
}
I will describe one situation :
Foo thread has finished copying all the data typed in last one minute and it has been 30 seconds since it is asleep. This thread unaware of the situation that several keys are being tapped when it is asleep,will never be able to copy the key strokes into the log file when one presses System.exit(0).
Is there any way I can interrupt this thread i.e awake it and ask it to copy the data to the log file.
Please discuss how should I approach this problem.
The situation in the question :
loop started
thread is sleeping and will sleep for 1 minute
after a minute,it gets the keys tapped in the last 1 minute and copies all that
to a file
Thread sleeps again..and will sleep for 1 minute before it copies the keystrokes
It has been about 30 seconds and thread will sleep for 30 seconds more before it starts
copying the key strokes
suddenly the user presses exit button in the application
The user wants that key strokes be recorded till the second he presses exit
I cannot do System.exit(0) before checking the thread is asleep or not
How do I do this. Should I awake it or make a different call to the list and get the
key strokes because they are being recorded ? And how shall I awake it ?
You're part way there...
while(isStarted) {
try {
Thread.sleep(60000); // sleep for 1 minute
} catch(InterruptedException exc) {
exc.printStackTrace();
}
ArrayList<String> keyStrokeList = nativeMethods.getKeyStrokeList();
int result = copy.copyToLogFile(keyStrokeList);
System.out.println(result);
}
What you need to is provide a way to terminate the loop...
public void dispose() {
isStarted = false;
interrupt();
try {
join();
} catch(InterruptedException exc) {
exc.printStackTrace();
}
}
You should also know that the JVM will not exit until all non-daemon threads have completed (under normal shutdown). This means you can call System.exit(0) and the JVM will not terminate until the logger thread has terminated.
You could use this, but attaching a shut down hook which would have the capacity to call the dispose method on the logger thread...just a thought
You should use a shared object between 2 thread to implement wait/notify pattern instead of Thread.sleep(..) method.
In your condition, there are 2 threads:
Which reads buffer at 1 min interval. (Thread1)
Which will receive "exit" event first. (Thread2)
So, whenever you create instance of Thread1 you can pass a Java Object (new Object()) to it. Reader thread can be put into sleep using object.wait(60*1000); So it will sleep for max 1 minute if object.notify() is not called in 1 minute. If object.notify() is called in this duration, thread will immediately resume.
So, whenever user wants to exit from application you can call object.notify(); which will resume reader thread.
If I failed to explain you the solution due to my bad English please let me know. I will provide you a code sample.
Here's a fairly simple test case to show a way to do this:
public class InterruptTest
{
#Test
public void test() throws InterruptedException
{
//Create the logging thread and start it
LogRunnable runnable = new LogRunnable();
Thread t = new Thread(runnable);
t.start();
//Wait some time
Thread.sleep(3500);
System.out.println("User has pressed exit, starting shutdown");
//Tell the runnable to shut down
runnable.halt();
//Interrupt the thread to wake it up
t.interrupt();
//Wait until thread terminates
t.join();
System.out.println("Exiting");
}
private static class LogRunnable implements Runnable
{
private static final int SLEEPMS = 2000;
private boolean isStarted = true;
private int runCount = 1;
public void halt()
{
this.isStarted = false;
}
public void run()
{
while(isStarted)
{
try
{
Thread.sleep(SLEEPMS);
}
catch(InterruptedException e)
{
System.out.println("Interrupted");
}
catch(Exception exc)
{
exc.printStackTrace();
}
//Do work
System.out.println("Work done " + runCount++);
}
}
}
}
Output:
Work done 1
User has pressed exit, starting shutdown
Interrupted
Work done 2
Exiting
When the user presses the exit key, you signal your main thread to start shutting everything down (in the test-case, it simply waits for some time)
The logging thread is told to halt and awakened via a interrupt() -call
Before exiting, the main thread calls join() to wait until the logging thread has completed, you could consider using an overload that takes a timeout in case something goes wrong
The logging thread wakes up with InterruptedException, completes the code after the catches and terminates
After the logging thread has terminated, the main-thread returns from the join()-call and terminates
I am reading Java Thread Programming a book by Paul Hyde.I am into intial chapter. I am running various sample programs in Eclipse IDE.
public class TwoThreadAlive extends Thread {
public void run() {
for (int i = 0; i < 10; i++) {
printMsg();
}
}
public void printMsg() {
// get a reference to the thread running this
Thread t = Thread.currentThread();
String name = t.getName();
System.out.println("name=" + name);
}
public static void main(String[] args) {
TwoThreadAlive tt = new TwoThreadAlive();
tt.setName("my worker thread");
System.out.println("before start(), tt.isAlive()=" + tt.isAlive());
tt.start();
System.out.println("just after start(),tt.isAlive()=" + tt.isAlive());
for (int i = 0; i < 10; i++) {
tt.printMsg();
}
System.out
.println("at the end of main(), tt.isAlive()=" + tt.isAlive());
}}
This program is giving SAME output every time I run it.But it has mentioned that output will differ as JVM will be busy in context switching.Can you please tell me that why it is giving same output?
And it is giving
at the end of main(), tt.isAlive()=true
This should have been
at the end of main(), tt.isAlive()=false
Please help me , this is making me mad.
Nope, the output is correct because by the time the main method executes the last println there is no guarantee that also your thread has finished executing. Add a tt.join(); right before the last print:
tt.join();
System.out
.println("at the end of main(), tt.isAlive()=" + tt.isAlive());
Now the main thread will be blocked until tt finishes, and so the println will execute only after tt is dead.
As for your output being always the same, 10 is a too fine grain value and most likely each thread finishes printing everything by the time it gets context switched. Try with a much larger value.
Not really clean readable code, I think the printMsg() should be static and maybe be placed inside the main class. That way you'll be able to notice that its behavior is not dependent on the custom thread class. Since it prints the current thread name, you could see (for a higher number of iterations) the JVM switching between your TwoThreadAlive thread and the main thread.
About the isAlive question, the TwoThreadAlive thread may not have finished its execution when the main finishes. Change the main thread iterations to 100 and the custom thread to 10000 to see this effect.
/* Multiple Threads Executing
* Author Myth17
*/
class T1 implements Runnable
{
public void run()
{
for(int c=0;c<10;c++)
System.out.println(Thread.currentThread().getName()+" running....");
}
}
class T2 implements Runnable
{
public void run()
{
for(int c=0;c<10;c++)
System.out.println(Thread.currentThread().getName()+" running....");
}
}
class T3 implements Runnable
{
public void run()
{
for(int c=0;c<10;c++)
System.out.println(Thread.currentThread().getName()+" running....");
}
}
class Rt
{
public static void main(String args[])
{
T1 j1=new T1();
T2 j2=new T2();
T3 j3=new T3();
Thread w1=new Thread(j1);
w1.setName("S");
Thread w2=new Thread(j2);
w2.setName("N");
Thread w3=new Thread(j3);
w3.setName("M");
w1.start();
w2.start();
w3.start();
}
}
If the loop runs up to 3 in the three for loops, in Linux Java JVM each thread executes serially as SSSNNNMMM (9 lines).
I changed the loop to run up to 10 in each for loops. I was expecting 30 lines and a change in order. But strangely S never executes and program exits!!
Shouldn't S get its chance sooner or later? As what I have read is that apart from deamon threads JVM shuts only after user thread complete.
alt text http://img36.imageshack.us/img36/6646/69458021.png
Did you realize that there are 8 lines of N in your output folder and 10 lines of M. It seems that the output window just displays 18 lines. S runs but you cannot see it.
Can you try incrementing loop to 20 instead of 10. I guess you will just see 18 lines of M.
(It seems that the problem is just not having a scroll bar on output window. Resize should work if exists.)
In your snippet neither of the threads are daemon. And until you set the threads as daemon via Thread#setDaemon() all the threads will execute completely before the app exits.
Recheck your problem!!
This should have worked. You could put log in the run() methods or debug it using break points.
You only have 18 lines showing in the window.
All of the "S" lines have scrolled off, as well as two of the "N" lines.
I tried running your code on a Windows Sun JVM 1.6 and as expected, I got 30 lines. What kind of JVM are you using?
All non daemon threads should finish before the JVM exists.