• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • paul wheaton
  • Ron McLeod
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:

Note on Thread

 
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi All
I got too many mails. Thanks all of you. Almost everyone is asking me about threads. The concern about threads could be understood, as it seems the toughest. So I thought I might share whatever little I could, regarding thread in the benefit of the group.
The thread has various states, new state, Runnable (ready-to run), Running, Blocked, Waiting pool, Lock pool, dead etc. (I have a nice diagram showing various stateo fthread, but I am unable to copy it here. Any Help!!!)
New State
When a thread is created, it is said to be in new state. Remember, when a thread is created, it does not start execution. The thread can be created by either creating a subclass of java.lang.Thread or by creating a class, which implements the interface java.lang.Runnable. In either case, override the public void run() method and define the code which you expect to be executed while the thread is running. REMEMBER THE SIGNATURE OF THE run() METHOD.
When the thread is in new state, the isAlive() method will return false. When the thread is created, its priority is set to the priority of the thread which created the thread.
Runnable (Ready-To-run)
When start() method called on new thread, the thread becomes Runnable. Remember that the thread does not start execution when the start() method is called. It may happen that it may not start forever (another running thread calls System.exit ()).
Remember, the start() method dose not call the run() directly, the Java Virtual Machine calls the run method of this thread. What it does is probably register the thread with thread scheduler (RHE). It throws IlleagleThreadStateException , if the thread was already started.
There are other scenarios also, where a thread becomes Runnable, which we will see later.
Running
When the thread is running, it executes code which is defined in the run() method. When the thread will run, can never be guaranteed. This depends on thread scheduler and which, in turn, depends on the underlying OS.
The model of preemptive scheduler is that many threads might be runnable, but only one thread is actually running. This thread continues to run until it ceases to be runnable or another thread of higher priority becomes runnable. In case of timesliced, equal amount of CPU time is given to each thread.
The JVM exits when all the working threads daemon threads or System.exit(0) is called.
Now consider the following code. Try to compile and run this code. How many times the value of i is printed? Now initialize the value of I at declaration time only and see the result. Now declare the variable i in the method itself instead of making it instance variable. See the result. This will give an idea about different possibilities regarding value of instance variable which are changed by different threads.
class TestThread{
public static void main(String args []){

Thread1 t1 = new Thread1();
Thread th1 = new Thread(t1);
Thread th2 = new Thread(t1);
th1.start();
th2.start();
}
}// End of TestThread
class Thread1 implements Runnable{
int i;
public void run(){

i = 0;
while(true){
System.out.println("Value of i = " + i++);
if ( i == 10)
break;
}
}
}
Dead Thread
When the execution of the run() method is over, the thread becomes dead thread. The dead thread can�t be started again. However the variables and methods of the dead thread can be accessed.
The stop() method also make the thread dead. Also if an exception is thrown and is uncaught, the thread becomes dead.
The isAlive () method will return false, if the thread is dead. Hence, the isAlive() method returns false only if the thread is in new state or is dead. All other time it returns true.
yield() � This is a static method. Use Thread.yield() to give other threads of the same priority a chance to execute. If other threads at the same priority are runnable, yield() places the calling thread into the Runnable pool and allows another thread to run. If no other threads are Runnable at the same priority, yield does nothing.
However, RHE mentions that there is no guarantee that when yield () is called, the thread with lower priority will not run. I tested the code, and it is found that the running thread doesn�t give up when yield is called and when only running threads are ones with lower priorities.
Blocked Thread
The Running thread can be blocked in many ways.
sleep(long time) - This is static method. It stops execution of the current thread and blocked for atleast the time as specified if it is not interrupted. The thread does not lose ownership of any monitors. Hence when the specified time is elapsed or the thread is interrupted, the thread becomes Runnable (not Running).
join() � The join method causes the current thread to wait until the thread on which the join method is called terminates or is interrupted or the specified time as argument to join method elapses.
I/O operation � if an executing thread calls any method which requires some input stream to be responded, then the thread waits for such input and hence is blocked. Any such blocking of thread will ensures that it releases the lock.
You may refer to following link to understand object lock, wait, notify, and interrupt, synchronization etc., as it provides very good explanation. Hence I thought no need to repeat the same.
http://www.javaranch.com/maha/Discussions/Threads/threads.html
Following are some of the things, which I would like to highlight:
When a thread receives notify/notifyAll , it goes to Object�s Lock Pool i.e. waits for the object�s lock, and once it acquires the lock, it becomes Runnable.
Calls to interrupt() are stored i.e. if interrupt() is called on a thread which is not blocked by sleep, wait, join etc. and doing something else, then it will continue with the work. When the thread, on which interrupt () was called, calls any of the above-mentioned methods, it will be interrupted immediately.
Calls to notify are not stored. A notify call can be issued without regard to whether any threads are waiting. If the notify method is called on an object when no threads are blocked in the wait pool for that object�s lock, the call has no effect.
When notify call is executed on a particular object, an arbitrary thread is moved from object�s wait poll to a lock pool. There is no way you can ensure that a particular thread will be moved out of object�s wait pool.
Wait method releases the lock on the current object only. If it has also acquired locks on some other objects, it does not release those locks.

Sources: RHE, Student Guide from Sun Educational Services, API documentation, special thanks to Maha Anna for excellent explanation on this topic (see the above mentioned link)
Correct me wherever I am wrong.
Hope this will be of some use to all.
Mukesh

[This message has been edited by Mukesh Rathod (edited October 21, 2000).]
 
Ranch Hand
Posts: 199
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Mukesh,
Thx for the info given. But can u explain in detail why the results of code is different in the 3 different situations.
Aruna

Now consider the following code. Try to compile and run this code. How many times the value of i is printed? Now initialize the value of I at declaration time only and see the result. Now declare the variable i in the method itself instead of making it
instance variable. See the result. This will give an idea about different possibilities regarding value of instance variable which are changed by different threads.
class TestThread{
public static void main(String args []){
Thread1 t1 = new Thread1();
Thread th1 = new Thread(t1);
Thread th2 = new Thread(t1);

th1.start();
th2.start();
}
}// End of TestThread
class Thread1 implements Runnable{
int i;
public void run(){
i = 0;
while(true){
System.out.println("Value of i = " + i++);
if ( i == 10)break;
}
}
}
 
Ranch Hand
Posts: 318
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It doesn't seem to me like they are all together different. You never started the first thread and the second 2 threads seem to have the same output. The thing that confuses me is that when I run it on my NT box, the two threads appear to run sequentially, not concurrently. I would think that you would see
i = 0
i = 1
i = 0
i = 2
i = 1
and so on as a result of the two processes haring the processors, but that doesn't happen i get one thread seemingly running to ompletion and then the other. I know you can't predict the thread scheduler, but this surprises me. In order to see the behavior that I am talking about, does there need to be a yield()?
Matt
 
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
All:
Mukesh, first of all, thanks for your time and effort in giving a very good material on Threads.
Also, I found one more resource on the net with info on Threads neatly presented. http://www.users.cts.com/sd/b/bambam/JavaII/Multithreading.html
Hope you find this useful too.
 
Viji Bharat
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Matt:
I believe Windows supports timeslicing, if that would help you. This info is provided in RHE.
 
Matt DeLacey
Ranch Hand
Posts: 318
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I was aware that Windows did timeslicing, but your post got me to thinking maybe there just wasn't a big enough slice of time. So I made the break statement so that it broke at 100 instead. Still no swapping between threads. Then, I upped it to 1000. THEN, I saw a swapping. But here is the funny thing. At around 620 the threads switched on the processor, which is pretty neat, BUT the first thread which was preempted at 620 never completed! The other thread went from 0 to 999 and the program terminated. So it looked like this Thread th1 went from 0 to 620 and then th2 went from 0 to 1000 and the program terminated. How on Earth did this happen???
Mat
 
Viji Bharat
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Matt:
I am trying to understand your post. If I am wrong, please correct me.

Looking at the code, it just prints "value of i" and the #. Since there are so many lines getting printed, it would have scrolled several pages up and the 'value of i' output that you have seen could be from execution of thread1 or thread2. So, it is possible that both the threads might have completed (which actually should be the case). I hope I have not confused you.
 
Matt DeLacey
Ranch Hand
Posts: 318
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Not true,
I piped the output to a file on the command line, so I could see exactly what was happening.

Matt
 
Viji Bharat
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Matt:
I tried this by adding print statements in the run method and I don't know if my observation correct but let me discuss it here.
Timeslicing makes th1 and th2 run for a certain amount of time in alternate successions. The run method has the while loop and the time slicing might result in each thread pausing execution when it is in the while loop, now the other thread resumes execution (again when in the while loop), alters i value and when this process repeats between these two threads and i reaches 10, control leaves the while loop. Atleast, this is my observation.
Please let me know if I am wrong or you have a better explanation of whats going on here.
 
Ranch Hand
Posts: 243
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Matt,
try to print like this :
Thread th1 = new Thread(t1,"th1");
Thread th2 = new Thread(t1, "th2");
...
...
System.out.println("Value of i = "+i++ +" "+Thread.currentThread().getName());
You will be able to observe the timeslicing more closely ( or from farther away ).
My personal opinion is that the time slicing is happening in large chunks but you cannot assume that it will happen every time at regular intervals. One thread may print 600 times, the other may print 1200 times.
If you let threads sleep (even for 0 ms ), then you will observe a totally different behavior.
 
Mukesh Rathod
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Aruna,
Hi Matt, Viji, hope this would also clarify your doubt.
Let's examine the cases one by one.
Case 1: As given.
Here the variable i is instance variable, hence if two threads are created using same object, both the thread will be referring to the same variable, so both the threads are updating the value of the variable and the result would be dependent on the underlying operating system.
Let�s consider timeslice (which I am using). First thread will be started, assume it continues execution for a while, then it will initialize the variable i = o, then increase the value of i and prints it. Now thread 2 will be started in between, it again initializes the value of i = 0 ( as i is initialized in run method) , then start printing the increasing values. Let�s assume, now again the first thread takes control, then it will continue with the value of i, where the second thread left (as both thread are referring to same object). Hence hereafter, whether the first thread is running or the second, they will print the incremental value of i until i becomes 10 i.e. last value printed would be 9.
The output should look like
Value of i = 0 // first thread is running
Value of i = 1
Value of i = 2
Value of i = 0 // second thread has started.
Value of i = 1 // either first or second thread is running.
Value of i = 2
Value of i = 3
Value of i = 4
Value of i = 5
Value of i = 6
Value of i = 7
Value of i = 8
Value of i = 9
On pre-emptive system, the first thread continues, prints 0 to 9 values, until it completes the execution and then second is started and again prints 0 to 9. (not sure about this behavior, as I haven�t tested it)
Case : 2 : Initialize the value of i at declaration time.
In this case, the part of code will look like,
class Thread1 implements Runnable{
int i = 0; // or int i;

public void run(){

while(true){ //rest of code
}
}// end of run
} // end of class
Here, the value of i will be initialized only once, when the object is created. Hence, no matter what is the underlying OS, no matter which thread is running, it will print values from 0 to 9 only once. So it will always print 10 values.

Case 3: variable i is local variable, instead of Instance variable.
The part of code now will look like
class Thread1 implements Runnable{

public void run(){

int i =0;
while(true){ //rest of code
}
}// end of run
}// end of class
Here, i is local variable of run method. Hence, both the threads keep separate copy of the variable. So both the threads will print value of i from 0 to 9. Hence, total 20 values of i will always be printed, the order of printing will be determined by which thread is running and which in turn depends on underlying OS.
Hope I am clear.
Mukesh
[This message has been edited by Mukesh Rathod (edited October 20, 2000).]
 
Aru Ven
Ranch Hand
Posts: 199
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
Can anyone explain "preemptive Scheduling" ?
Aruna
[This message has been edited by Aru Ven (edited October 20, 2000).]
 
Matt DeLacey
Ranch Hand
Posts: 318
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmmm..not sure I'm making myself clear. I added what mohit suggested so I could explicitly see which thread was running (also of course the loop has changed to 1000 so I can see one thread getting swapped for the other because I couldn't see that when the loop was just to 10 because of time slicing and I piped the result out to a file). However, the result is as I saw before (or thought i was seeing). One thread goes from 0 - 625 (of course each time you run it's different but somewhere around 620)...then the next thread prints from 0 - 999 and the program terminates. The first thread never goes from 625 (or whatever) to 999!!! This is what I don't understand. Mukesh, you come the closest to addressing what I'm asking, but it is NOT behaving the way you suggest. This is puzzling...any more ideas?

Matt
 
Matt DeLacey
Ranch Hand
Posts: 318
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mukesh,
You said that both threads are referring to the same i and so they are updating the same. If that is true then:
1.) Why do you start the value of i for the second thread at 0?
2.) Wouldn't i need to be static for that to be true?
Matt
 
Viji Bharat
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Matt:
If I have understood Mukesh correctly, then both threads th1 and th2 are created using the "same" runnable object t1. So, there is only one variable i here.
Now, when th1 is running i.e run method is executed, var i is initialized to 0. Then i gets incremented for a while when th1 is running. When th2 gets to run, it will execute run method, where i is again initialized (this is strictly resetting value of i to 0) and as the loop continues, i gets incremented.
HTH

 
Mukesh Rathod
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Matt,
I hope whatever viji is saying is clear to u. In first case, as I mentioned, the variable i is initialized to 0 in th erun method itself. So whenever any thread starts running, it will reset the value of i to 0. Now look at second case, the value of i is not initialized in run method, instead it is initialized at time of declaration. Hence it will print values 0 to 9 only, irrespective of any number of threads running on same object.
Hope I am clear.
Mukesh
 
Mukesh Rathod
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Aruna,
In java technology, threads are usaually preemptive, howevr, this depends on underlying OS. (refer RHE)
The model of preemtive scheduler is that many threads might be runnable, but only one thread is actully running. This thread continues to run until it ceases to be runnable or another thread of higher priority becomes runnable. In later case, the lower priority thread is preeemted by the thread of higher priority, which gets a chance to run instead.
Where as in timeslice, each thread gets an equal amount of time to execute.
Mukesh.

[This message has been edited by Mukesh Rathod (edited October 20, 2000).]
 
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mukesh, that was a nice summary on threads. There is one thing I want to bring up.
<Q>I/O operation � if an executing thread calls any method which requires some input stream to be responded, then the thread waits for such input and hence is blocked. Any such blocking of thread will ensures that it releases the lock.</Q>
Is that true? I think blocking for I/O does not release any locks that are held. Try the following code for example.
<CODE>
import java.io.*;
public class r implements Runnable {
static byte[] b = new byte[0];
String name;
r(String name) { this.name = name; }
public void run() {
synchronized (b) {
for (int count=0; count<10; count++) System.out.println(name + count);
int i = 0;
try { while (i!=-1) {
i = System.in.read();
System.out.println(name + i);
}
} catch(IOException ioe) { System.out.println(name + "IOException"); }
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new r("first thread - "));
t1.start();
Thread t2 = new Thread(new r("second thread - "));
t2.start();
}
}
</CODE>
When you run this code, the first thread prints 0 to 9 and then blocks for I/O. But it does not relinquish the lock. If it did, the second thread would have printed 0 to 9 immediately after the first thread prints 9. But in fact, the second thread prints 0 to 9 only after the first thread completes I/O.
Note:- Press the end of file indicator (CTRL-Z on PCs) to stop reading from System.in
Do all agree ?
 
Mukesh Rathod
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Thomas,
what you r doing is synchronizing the thread on other object (b). Well, whenevr the thread releases the lock , it releases the lock on current object, lock on any other objects are not released. So instead of synchronized(b) try, synchronized(this), then once the first thread waits for Input, the second will print 0 to 9.
Hope this is clear now.
Mukesh

 
Matt DeLacey
Ranch Hand
Posts: 318
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I appreciate everybody's patience, and I hate to be so slow, but I STILL do not understand why BOTH threads do not run to completion. As I said when I up the break condition to 1000 one thread runs from 0-625 (or so) and then the other runs from 0-999 and the program terminates. Why doesn't the first thread then resume and go from 626-999? I piped the results out to a file and I made it so I could see which thread was executing at any given time as per mohit's suggestion, so I believe that even though my understanding lacks something to be desired, I am actually seeing what I think I am actually seeing. Baby steps. Can anyone answer this?
Matt DeLacey
 
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hello Mukesh,
if this blocking IO operation [ System.in.read() ] is releasing the
lock of the object, can u please explain y the 2nd thread not printing the
"name + count" in the for loop[ after the 1st thread prints from 1 .. 3 ], inside the synchronized block ?

import java.io.*;
class r implements Runnable {
static byte[] b = new byte[0];
String name;
r(String name) { this.name = name; }
public void run() {
//orginal code --> synchronized (b)
// modified code
synchronized (this) {
for (int count=0; count<3; count++) System.out.println(name + count);
int i = 0;
try {
//while (i!=-1) {
i = System.in.read();
System.out.println(name + i);
//}
} catch(IOException ioe) { System.out.println(name + "IOException"); }
}
}
public static void main(String[] args) {
// modified code
r myThread = new r("me");
Thread t1 = new Thread(myThread);
t1.start();
Thread t2 = new Thread(myThread);
t2.start();

}
}


[This message has been edited by Jon Aryan (edited October 23, 2000).]
 
Sheriff
Posts: 5782
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am transferring this GREAT discussion to Threads and Synchronization... where it belongs.
Ajith
 
Viji Bharat
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Jon Aryan:
I tried your code and it does print name + count for the second thread until read() is called when the second thread is running.
 
Jon Aryan
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Viji,
U mean 2 say, the 2nd thread prints 0 .. 2, without pressing the ENTER key ?? !. [ I (still !) believe the "blocked" thread is not releasing the lock of the object ( thatz wat am seeing !!) ]
please modify the for loop like
for (int count=0; count<3; count++) {<br /> System.out.println("Hash code of the thread --> " + Thread.currentThread().hashCode() );
}

[This message has been edited by Jon Aryan (edited October 24, 2000).]
[This message has been edited by Jon Aryan (edited October 24, 2000).]
[This message has been edited by Jon Aryan (edited October 24, 2000).]
 
Viji Bharat
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Jon:
Yes, I checked the o/p with Thomas' code and thread names as 'First' and 'Second' and I get the o/p
First0
Second0
First1
Second1
First2
Second2
read called
read called
In your example, I find that you give the same name 'me' for both threads. Did you try giving both threads diff names and check what o/p you get?
 
Ranch Hand
Posts: 107
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all,
I was going through this forum when I came across this beautiful explanation titled "Note on Thread" posted by Mr. Mukesh Rathod. I tried the example given by Mr. Rathod for the three cases given i.e,
Case 1: If 'i' were an instance variable which is initialised within the 'run' method.
Case 2: If 'i' were an instance variable which is initialised at the time of declaration.
Case 3: If 'i' were a local varaible of the 'run' method.
I am using Windows 98. In both the first and the last case, I got the following output
Value of i = 0
Value of i = 1
Value of i = 2
Value of i = 3
Value of i = 4
Value of i = 5
Value of i = 6
Value of i = 7
Value of i = 8
Value of i = 9
Value of i = 0
Value of i = 1
Value of i = 2
Value of i = 3
Value of i = 4
Value of i = 5
Value of i = 6
Value of i = 7
Value of i = 8
Value of i = 9
so, I guess that the OS is a pre-emptive system.
In the second case, the program went into an infinite loop, not breaking when 'i' became equal to 10.
Can anybody explain this behaviour to me? Also I want to confirm whether is it a pre-emptive OS that I am using?
Thanks in advance.
Kezia.
 
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm not sure if this post is redundent but here goes for the fun of it:
1) RE:
===========
It doesn't seem to me like they are all together different. You never started the first thread and the second 2 threads seem to have the same output. The thing that confuses me is that when I run it on my NT box, the two threads appear to run sequentially, not concurrently. I would think that you would see
i = 0
i = 1
i = 0
i = 2
i = 1
--------------------
This is easy. The program is too small to involve time slicing, as someone correctly pointed out.
2)

RE:
======================
I was aware that Windows did timeslicing, but your post got me to thinking maybe there just wasn't a big enough slice of time. So I made the break statement so that it broke at 100 instead. Still no swapping between threads. Then, I upped it to 1000. THEN, I saw a swapping. But here is the funny thing. At around 620 the threads switched on the processor, which is pretty neat, BUT the first thread which was preempted at 620 never completed! The other thread went from 0 to 999 and the program terminated. So it looked like this Thread th1 went from 0 to 620 and then th2 went from 0 to 1000 and the program terminated. How on Earth did this happen???
-------------------
This happens because the original code is broken.. Let me explain...
here's the code with line numbers:
1: class TestThread{
2: public static void main(String args []){
3: Thread1 t1 = new Thread1();
4: Thread th1 = new Thread(t1);
5: Thread th2 = new Thread(t1);
6: th1.start();
7: th2.start();
8: }
9: }// End of TestThread
10: class Thread1 implements Runnable{
11: int i;
12: public void run(){
13: i = 0;
14: while(true){
15: System.out.println("Value of i = " + i++);
16: if ( i == 10)break;
17: }
18: }
19: }

Lines 3,4, 5 and 11 are very stange because here we a runnable object that inherits is put into a thread and then started. So basically one single object is used by two threads. The object (of class Thread1) has an instance variable i. What results is a classic synchronization problem. Two threads modifying one variable i. This leads to, assuming time slicing gets involved, one thread finishing and the other thread going into an inf loop.
Here's some code that works:
Working code 1:
1: class TestThread{
2: public static void main(String args []){
3: Thread1 t1 = new Thread1();
4: Thread th1 = new Thread(t1);
5: Thread th2 = new Thread(t1);
6: th1.start();
7: th2.start();
8: }
9: }// End of TestThread
10: class Thread1 implements Runnable{
11: public void run(){
12: int i; //the varible "i" has been moved here.
13: i = 0;
14: while(true){
15: System.out.println("Value of i = " + i++);
16: if ( i == 10)break;
17: }
18: }
19: }

Working code 2:
1: class TestThread{
2: public static void main(String args []){
3: //this line is gone.
4: Thread th1 = new Thread1(); //change here.
5: Thread th2 = new Thread1(); //change here.
6: th1.start();
7: th2.start();
8: }
9: }// End of TestThread
10: class Thread1 extends Thread{
11: int i;
12: public void run(){
13: i = 0;
14: while(true){
15: System.out.println("Value of i = " + i++);
16: if ( i == 10)break;
17: }
18: }
19: }

to see the time slicing you need to set the break at around 1000 or even higher depending on the speed of your machine.
For added fun try running this code:
1: class TestThread{
2: public static void main(String args []){
3: //this line is gone.
4: Thread th1 = new Thread1(); //change here.
5: Thread th2 = new Thread1(); //change here.
6: th1.start();
7: th2.start();
8: }
9: }// End of TestThread
10: class Thread1 extends Thread{
11: int i;
12: public void run(){
13: i = 0;
14: while(true){
15: System.out.println("Value of i = " + i++);
16: try {yeild();} catch (Exception ex) {}
17: if ( i == 10)break;
18: }
19: }
20: }
yeild() tells the thread to yeild the processor and give other threads a chance to run. This means the output should be more staggered.

------------------
 
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I know this is an OLD thread, but I'll post a reply anyway:
re: Matt's question [why did the second thread not continue with i=621 after the second thread completed].
Both threads (th1 and th2) are referring to the same Runnable object (t1). So they are referencing the same variable i. To explain what is going on I'm going to use a simplified case, using 5 as the breaking point. Assume the following sequence occurs:
t0: th1 begins running
t1: th1 sets i to zero ([i=0;]
t2: th1 prints 1=0 and sets i to 1.
t3: th1 prints 1=1 and sets i to 2.
t4: th1 prints 1=2 and sets i to 3.
t5: task switch. th2 becomes active thread
current execution point for th1: if( i == 5 ) break;
t6: th2 sets i to zero
t7: th2 prints 1=0 and sets i to 1.
t8: th2 prints 1=1 and sets i to 2.
t9: th2 prints 1=2 and sets i to 3.
t10: th2 prints 1=3 and sets i to 4.
t11: th2 prints 1=4 and sets i to 5.
t12: th2 completes execution and switches to the dead state.
th1 moves to running state.
t13: th1 executes the line if( i == 5 ) break; Since i has the value 5, the loop is broken and the thread finishes execution.
Even though i had the value 3 when th1 was switched out, when it is switched back to the running state it has the value 5 (because th1 and th2 are updating the same instance of the Thread1 class).
re: Kezia's question [why it went into an infinite loop].
If the first thread interrupts right before it increments i, and the second thread finishes the loop, then when the first thread continues, i will already have the value 10. The first thread will then increment the value to 11. Once the value is higher than 10, the first thread will continue looping until i overflows and loops back around to the value 10 (which will require over 4 billion increments).
 
reply
    Bookmark Topic Watch Topic
  • New Topic