#Java Multi-Threading Part I
##Lesson1 : Basic Threads ###1. Extends Thread
/*
* Basic Threads
* Run Concurently(Simultaneously)
*/
public class App {
public static void main(String[] args) {
Runner runner1 = new Runner();
runner1.start(); //Reason use start() ==> want to run Simultaneously
Runner runner2 = new Runner();
runner2.start();
}//ENDof Main
}
class Runner extends Thread{
@Override
public void run() {
for(int i = 0; i < 10; i++){
System.out.println("Hello: " + i);
try {
Thread.sleep(100); //in MilliSeconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}//ENDof run
}
OUTPUT
Hello: 0
Hello: 0
Hello: 1
Hello: 1
Hello: 2
Hello: 2
Hello: 3
Hello: 3
Hello: 4
Hello: 4
Hello: 5
Hello: 5
Hello: 6
Hello: 6
Hello: 7
Hello: 7
Hello: 8
Hello: 8
Hello: 9
Hello: 9
###2. Implement Runnable
/*
* Basic Threads
* Run Concurently(Simultaneously)
*/
public class App {
public static void main(String[] args) {
Thread thread1 = new Thread(new Runner());
thread1.start(); //Reason use start() ==> want to run Simultaneously
Thread thread2 = new Thread(new Runner());
thread2.start();
}//ENDof Main
}
//Implements Runnable
class Runner implements Runnable{
@Override
public void run() {
for(int i = 0; i < 10; i++){
System.out.println("Hello: " + i);
try {
Thread.sleep(100); //in MilliSeconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}//ENDof run
}
OUTPUT
Hello: 0
Hello: 0
Hello: 1
Hello: 1
Hello: 2
Hello: 2
Hello: 3
Hello: 3
Hello: 4
Hello: 4
Hello: 5
Hello: 5
Hello: 6
Hello: 6
Hello: 7
Hello: 7
Hello: 8
Hello: 8
Hello: 9
Hello: 9
###2. Shorter(implements Runnable())
/*
* Basic Threads
* Run Concurently(Simultaneously)
*/
public class App {
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable(){
@Override
public void run() {
for(int i = 0; i < 10; i++){
System.out.println("Hello: " + i);
try {
Thread.sleep(100); //in MilliSeconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}//ENDof RUN
});
thread1.start(); //Reason use start() ==> want to run Simultaneously
}//ENDof Main
}
OUTPUT
Hello: 0
Hello: 1
Hello: 2
Hello: 3
Hello: 4
Hello: 5
Hello: 6
Hello: 7
Hello: 8
Hello: 9
##Lesson2 : Basic Threads Synchronization
###Problem Encountered ??
/*
* Basic Threads Synchronization
* Run Concurently(Simultaneously)
*/
/*
* 2 Problems :
* Sharing more than 1 threads --> Sharing the same DATA
*/
public class App {
public static void main(String[] args) {
Processor proc1 = new Processor();
proc1.start();
}//ENDof Main
}
class Processor extends Thread{
@Override
public void run() {
while(true){ //Infinite Loop
System.out.println("Hello");
try {
Thread.sleep(100);//MilliSeconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}//Endof RUN
}
Al'right look at the code below on how to terminate the processor by using Thread interruptions.
###Solution 1 : Use "Volatile" keywords
volative
is used to prevent threads from caching variables.
/*
* Basic Threads Synchronization
* Run Concurently(Simultaneously)
*/
/*
* 2 Problems :
* Sharing more than 1 threads --> Sharing the same DATA
*/
public class App {
public static void main(String[] args) {
Processor proc1 = new Processor();
proc1.start();
}//ENDof Main
}
class Processor extends Thread{
@Override
public void run() {
while(true){ //Infinite Loop
System.out.println("Hello");
try {
Thread.sleep(100);//MilliSeconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}//Endof RUN
}
###Solution 2: Synchronized Keyword
/*
* Synchronized Keyword
* Run Concurently(Simultaneously)
*/
/*
* 2 Problems :
* Sharing more than 1 threads --> Sharing the same DATA
*/
public class App {
private int count = 0;
public static void main(String[] args) {
App app = new App();
app.doWork();
}//ENDof Main
//
//Use SYNCHRONIZED ///////////////
public synchronized void increment(){
count++;
}
public void doWork(){
Thread thread1 = new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 10000; i++){
increment();
}
}
});
Thread thread2 = new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 10000; i++){
increment();
}
}
});
thread1.start();
thread2.start();
//Wait for the thread to Finish
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Count is " + count);
}//ENDof doWork()
}
OUTPUT
Count is 20000
##Lesson3 : Multiple Locks => Use Synchronized Code Blocks
###1. Simple Worker.java
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Worker {
private Random random = new Random();
private List<Integer> list1 = new ArrayList<Integer>();
private List<Integer> list2 = new ArrayList<Integer>();
public void stageOne() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
list1.add(random.nextInt(100));
}
public void stageTwo() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
list2.add(random.nextInt(100));
}
public void process(){
for(int i = 0; i < 1000; i++){
stageOne();
stageTwo();
}
}
public void main() {
System.out.println("Starting ....");
long start = System.currentTimeMillis();
process();
long end = System.currentTimeMillis();
System.out.println("Time take: " + (end-start) + " ms");
System.out.println("List 1 Length: " + list1.size() +
"; List 2 Length: " + list2.size());
}
}
App.java
/*
* Multiple Locks: Use of Synchronized Code Blocks
* Run Concurently(Simultaneously)
*/
public class App {
public static void main(String[] args) {
new Worker().main();
}//ENDof Main
}
OUTPUT
Starting ....
Time take: 2850 ms
List 1 Length: 1000; List 2 Length: 1000
###2. A Little Better (Process @ the same time)... Worker.java
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Worker {
private Random random = new Random();
private List<Integer> list1 = new ArrayList<Integer>();
private List<Integer> list2 = new ArrayList<Integer>();
//Synchronized => Enquire the monitor log => Slow process
public synchronized void stageOne() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
list1.add(random.nextInt(100));
}
public synchronized void stageTwo() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
list2.add(random.nextInt(100));
}
public void process(){
for(int i = 0; i < 1000; i++){
stageOne();
stageTwo();
}
}
public void main() {
System.out.println("Starting ....");
long start = System.currentTimeMillis();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
process();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
process();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("Time take: " + (end-start) + " ms");
System.out.println("List 1 Length: " + list1.size() +
"; List 2 Length: " + list2.size());
}
}
OUTPUT
Starting ....
Time take: 5763 ms
List 1 Length: 2000; List 2 Length: 2000
###3. Slow Proces ???...... Use this
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Worker {
private Random random = new Random();
private Object lock1 = new Object();
private Object lock2 = new Object();
private List<Integer> list1 = new ArrayList<Integer>();
private List<Integer> list2 = new ArrayList<Integer>();
/*
* Multiple Locks: Use of Synchronized Code Blocks
* Run Concurently(Simultaneously)
*/
//Synchronized => Enquire the monitor log => Slow process
//Having Multiple Threads will slow down
// So.... use this method to ... make the process a little faster
public void stageOne() {
//Only 1 Thread @ a time -> Faster process
synchronized(lock1){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
list1.add(random.nextInt(100));
}
}
public synchronized void stageTwo() {
//Only 1 Thread @ a time -> Faster process
synchronized(lock2){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
list2.add(random.nextInt(100));
}
}
public void process(){
for(int i = 0; i < 1000; i++){
stageOne();
stageTwo();
}
}
public void main() {
System.out.println("Starting ....");
long start = System.currentTimeMillis();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
process();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
process();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("Time take: " + (end-start) + " ms");
System.out.println("List 1 Length: " + list1.size() +
"; List 2 Length: " + list2.size());
}
}
OUTPUT
Starting ....
Time take: 2852 ms
List 1 Length: 2000; List 2 Length: 2000
##Resources