public class MultiThreaded extends Thread {
public static void main(String[] args) {
MultiThreaded mt = new MultiThreaded();
mt.start();
for (int i = 0; i < 500; i++) {
System.out.println("main thread");
}
}
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("other thread");
}
}
}
The output will be interleaving "main thread" and "other thread". The output order is not sequential nor gauranteed.
When you invoke the start,
JVM will create a separate thread and it will invoke the run method internally.
for (int i = 0; i < 500; i++) {
System.out.println("main thread");
Thread.sleep(1000);
}
Thread.sleep(milliseconds), 1000 millisecond = 1 second
Usage: If we are waiting for a particular resource, e.g. access to database, but it is not available now. Can put thread into sleep and let it try again later.
Join Method
In the Thread class. Every class that extends Thread class will inherit it.
public class JoinDemo extends Thread {
static int sum = 0;
public static void main(String[] args) {
JoinDemo jd = new JoinDemo();
jd.start();
System.out.println("before sum is " + sum);//before sum is 0
try {
jd.join();
} catch (InterruptedException e) {
System.out.println("join interrupted");
}
System.out.println("sum is " + sum);//sum is 10
}
public void run() {
for (int i = 0; i < 5; i++) {
sum += i;
try {
Thread.sleep(100);
} catch (InterruptedException e){
System.out.println("sleep interrupted");
}
}
}
}
So the join method will make sure that this particular thread on which the join is invoked, will complete
and go to a dead state only then it will execute any other threads. so the main method is waiting for join thread to complete.
Thread Priority
Thread t = new Thread();
t.setPriority(7);
Priority is an integer value and range from 1 to 10, 10 is the highest priority.
Normally, priority is five, that is default for any thread.
Although programmer can set the priority, there is no guarantee that they will execute in the order. It depends on JVM implementation, the thread scheduler. But in most case, it works.
Thread.yield() will yield the current thread to the main thread.
Use Runnable Interface
Thread Interruption
public class MyThread {
public void run() {
try {
for (int i = 0; i < 10; i++) {
System.out.println("I am a lazy thread");
Thread.sleep(2000);
}
} catch (InterruptedException e) {
System.out.println("got interrupted");
}
}
}
public class InterruptDemo {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
t.interrupt();
System.out.println("End of the main thread");
}
}
output:
End of the main thread
I am a lazy thread
got interrupted
So I am a lazy thread got printed only once.
The for loop did not continue because we have interrupted that thread from the main thread.
If comment out t.interrupt(), it will print out "End of the main thread" and print out "I am a lazy thread" every 2 second.
So we can only interrupt a thread that is in sleep mode.
Synchronized Keyword (object level)
The first thread will lock the object. Acquiring and releasing the lock is taken care of by the JVM.
Once a method is marked as synchronized no other thread can access this method as well as any other synchronized
method on that object.
Synchronization is at the object level not at the method level.
Class Level Lock
Every class in Java has a unique lock. If a thread wants to execute a static synchronized method it will first get the class level lock.
For example:
t1 holds the lock so neither t2 nor t3 can access static synchronized method. However, other method on class are still accessible.
Synchronized Block
The advantage is that multiple threads can enter this method and execute the code before the synchronized code.
Three way to implement it:
- by passing the reference to the current object which will lock the current object
- pass in any object and the current thread will get a lock on that object
- class level lock by passing in the class name
Inter-Thread Communication
Using wait, notify and notifyAll method to communicate
t1 is using and locking the object but t1 need t2 to finish its job first. Hence, t1 can call wait() and give up the lock. At the same time, t1 will be pushed into a wait state. T2 takes the lock, finishes its job and then, notify(). When notify(), t2 will release the lock on the object. T1 will be notified and start running again.
These method should be used in synchronized context, e.g. synchronized method, synchronized block.
wait(): the thread might not give up the lock right away, it might take some time the release the lock
notify(): release lock right away and threads waiting for the lock can take the lock
Example
public class MyThread extends Thread {
int total;
public void run() {
System.out.println("Child thread is calculating the sum");
synchronized(this) {
for (int i = 0; i < 10; i++) {
total += i;
}
this.notify();
}
}
}
public class MainThread {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
synchronized(t) {
System.out.println("Main Thread is going to wait");
t.wait();
System.out.println("Main thread notified");
System.out.println(t.total);
}
}
}
flow: main thread runs, starts the child thread. Once the main thread enters into synchronized block, it gets the lock on the object, t. The main thread releases the lock by invoking the wait method. Then the child thread gets the lock. After it finishes its work, it calls notify method and releases the lock. Then the main thread can get the lock and finishes its job.