Reputation: 75
I learned that threads can lock onto "the resources", let's say an object, they're using so that only one at a time is allowed to use and modify it which is the problem of synchronization. I created two different instances of one class and fed it to my threads, trying to make sure they're locking on different "resources". How ever they still behave as though they've locked on same resources? I'm confused as I haven't had any experience and knowledge regarding threads.
So this is a code I modified from an online tutorial to try what I was thinking about:
public class TestThread {
public static void main(String args[]) {
PrintDemo PD1 = new PrintDemo("No.1"); //just prints from 1 to 5
PrintDemo PD2 = new PrintDemo("No.2");
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD1 );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD2 );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
threadName = name;
PD = pd;
}
public void run() {
synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
class PrintDemo {
private String name;
PrintDemo(String name) {
this.name = name;
}
public void printCount() {
try {
for(int i = 5; i > 0; i--) {
System.out.println(name + " Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
It should be different each time I run, but it always the same:
output:
Starting Thread - 1 Starting Thread - 2 No.1 Counter --- 5 No.1 Counter --- 4 No.1 Counter --- 3 No.1 Counter --- 2 No.1 Counter --- 1 Thread Thread - 1 exiting. No.2 Counter --- 5 No.2 Counter --- 4 No.2 Counter --- 3 No.2 Counter --- 2 No.2 Counter --- 1 Thread Thread - 2 exiting.
edit #1: I put the entire code as you asked. i also tested the code without overriding start. it had the same result.
Upvotes: 0
Views: 46
Reputation: 27115
The problem is in your ThreadDemo.start()
method.
Your ThreadDemo
class is declared with extends Thread
, but you never actually use it as a thread. Instead, the real thread objects are created inside ThreadDemo.start()
.
t = new Thread (this, threadName);
t.start ();
Here's what probably is happening:
Main thread calls T1.start()
. It creates a new thread, which takes some time, and then it starts the thread.
The new thread starts printing its five lines, while the main thread simultaneously calls T2.start()
.
The T2.start()
call creates another new thread, which takes some time. Meanwhile, the other thread still is printing. It doesn't print very many lines, and system.out
is buffered, so chances are, it is able to print all of them before any actual I/O happens. Meanwhile...
...The main thread still is creating that T2
thread. It takes some time.
Finally, the main thread is able to start the T2
thread, which prints its five lines, and...
...end of story. That's how it probably goes down.
Upvotes: 0
Reputation: 213
If you add a
Thread.sleep(1000)
between each tick of your PrintDemo, you will likely see that both threads do 5, then 4, then 3, etc. Right now the first thread is being too fast, it completes faster than the 2nd thread can be started by the main thread.
Synchronization has no effect here, both threads synchronize on different resources, which has no effect. After proving (with the Thread.sleep) that both threads execute at the same time, then add synchronization on a shared object, and both threads will fully execute one after the other, even with the waiting.
Upvotes: 1