I am trying to learn multi-threading in java. I wrote this sample code, to get a random number and exit if the number is positive integer. Here I am using synchronized just to check how it works. Since the method gererateRandom() is synchronized my expectation is that only one thread is allowed to go inside the function. Although there is no shared variable I am just checking how it works.
The program is working fine, but what I am expecting is, as the thread gets a positive number it should exit the program and other threads should be blocked. But the result I am getting is completely different. Please check the result section below the code.
import java.util.Random;
public class CheckNumbnerThread implements Runnable{
Thread t;
int n ;
CheckNumbnerThread() {
t = new Thread(this);
System.out.println("Child thread: " + t);
t.start(); // Start the thread
}
#Override
public void run() {
gererateRandom();
}
public synchronized int gererateRandom(){
Random rn = new Random();
n = rn.nextInt() % 100;
System.out.println("The random number generated is " + n);
if (n > 0){
System.exit(0);
}
return n;
}
}
public class DemoThread {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int counter = 0;
while(true){
new CheckNumbnerThread();
counter++;
System.out.println("Thread counter " + counter);
}
}
}
Child thread: Thread[Thread-0,5,main]
Thread counter 1
Child thread: Thread[Thread-1,5,main]
The random number generated is 79
Thread counter 2
Child thread: Thread[Thread-2,5,main]
The random number generated is 27
Thread counter 3
Child thread: Thread[Thread-3,5,main]
The random number generated is -7
Thread counter 4
Child thread: Thread[Thread-4,5,main]
The random number generated is -68
Thread counter 5
Child thread: Thread[Thread-5,5,main]
The random number generated is 20
Thread counter 6
Child thread: Thread[Thread-6,5,main]
The random number generated is 67
Thread counter 7
Child thread: Thread[Thread-7,5,main]
The random number generated is 13
Thread counter 8
Child thread: Thread[Thread-8,5,main]
The random number generated is 56
Thread counter 9
Child thread: Thread[Thread-9,5,main]
The random number generated is 93
But what I expected is that it should stop execution after printing:
Child thread: Thread[Thread-0,5,main]
Thread counter 1
Child thread: Thread[Thread-1,5,main]
The random number generated is 79
Your synchronized applies to the instance of that thread only and will not prevent the method running in parallel on multiple threads like your code does. If you want to synchronize on all instances, synchronize on class.
synchronized (CheckNumbnerThread.class) {
n = rn.nextInt() % 100
// ...
}
that's not the idea. since you've synchronized the method gererateRandom(), what you're assuring is that no more than one thread will execute this method at the same time.
but since there's no restriction for this method execution, what is happening is that all your threads will just wait for their time to execute this method, but all of them will be executed.
Related
So I have a simple code that I want to print the value I 10 times with Thread1, after that 10 times of Thread2 and at the end, print the count ( it should be 20). I am using the ".join()" but the result is executing random times of Thread1 and Thread2 and then the Sum is correct. How can is it possible to print first all the Thread's1 loop and then the Tread's2 ??
class MyClass extends Thread {
public static synchronized void incount() {
SimpleThreads.count++;
}
public void run() {
for(int i=0; i<10; i++) {
incount();
System.out.println(Thread.currentThread().getId()+" value : " + i);
}
}
}
public class SimpleThreads {
static int count=0;
public static void main(String[] args) {
MyClass thread1 =new MyClass();
MyClass thread2 =new MyClass();
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" Sum : "+count);
}
}
The Result :
11 value : 0
10 value : 1
11 value : 1
10 value : 2
11 value : 2
10 value : 3
11 value : 3
11 value : 4
11 value : 5
11 value : 6
11 value : 7
11 value : 8
11 value : 9
10 value : 4
10 value : 5
10 value : 6
10 value : 7
10 value : 8
10 value : 9
Sum : 20
You are starting Thread2 before calling the join() on thread1.
That is why your both threads are basically running simultaneously and your join is not affecting the run() of any other the 2 threads.
Try to change your start and join calling code to something like this;
try{
thread1.start();
thread1.join();
thread2.start();
}
You shouldn't need to call join() on thread2 in this case.
If you want thread2 to start after thread1 terminates, then of-course you can simply wait for thread1 to terminate and then launch thread2. But then, what is the point of using threads?
If you want to launch thread1 and thread2 at the same time and still have thread2 wait until thread1 terminates, you can use one of Java's many concurrency utilities, such as Semaphore
The below code demonstrates the use of Semaphore. As you can see, just as in the code in your question, both threads - thread1 and thread2 - are launched at the same time. In the run() method of class MyClass, the code tries to acquire the semaphore. Method acquire() will block, i.e. it will not return, until it succeeds in acquiring the semaphore. Hence the first thread that manages to acquire the semaphore will run, while the other thread will wait until the first thread releases the semaphore. Note that I create the semaphore with only one permit which means that only one thread can acquire the semaphore at any one time. If you change the 1 to a 2 in the call to the Semaphore constructor, you will get exactly the same behavior as in your original code in your question, i.e. both threads will run simultaneously because both can immediately acquire the semaphore.
Note also that since I am using a semaphore, I don't need to call Thread.join() at all in order to have one thread wait until the other completes, but since you want to print the "sum" in the "main" thread, the "main" thread needs to wait, but it only needs to wait for the second thread to terminate.
Here is the code:
import java.util.concurrent.Semaphore;
class MyClass extends Thread {
private Semaphore semaphore;
public MyClass(Semaphore semaphore) {
this.semaphore = semaphore;
}
public static synchronized void incount() {
SimpleThreads.count++;
}
public void run() {
try {
semaphore.acquire();
for (int i = 0; i < 10; i++) {
incount();
System.out.println(Thread.currentThread().getId() + " value : " + i);
}
}
catch (InterruptedException xInterrupted) {
xInterrupted.printStackTrace();
}
finally {
semaphore.release();
}
}
}
public class SimpleThreads {
static int count = 0;
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(1);
MyClass thread1 = new MyClass(semaphore);
MyClass thread2 = new MyClass(semaphore);
thread1.start();
thread2.start();
try {
thread2.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" Sum : " + count);
}
}
And here is the output obtained when running the above code:
13 value : 0
13 value : 1
13 value : 2
13 value : 3
13 value : 4
13 value : 5
13 value : 6
13 value : 7
13 value : 8
13 value : 9
14 value : 0
14 value : 1
14 value : 2
14 value : 3
14 value : 4
14 value : 5
14 value : 6
14 value : 7
14 value : 8
14 value : 9
Sum : 20
I am new to multithreading. I have a volatile variable currentPrimeNo and it will print the next prime number as implemented in run method for every new thread. But everytime I am getting currentPrimeNo as 0 for every thread. How should I keep the global variable currentPrimeNo updated?
public class Processor implements Runnable {
private int id;
private static volatile int currentPrimeNo = 0;
public Processor(int id) {
this.id = id;
}
#Override
public void run() {
System.out.println("Starting process id: " + id);
currentPrimeNo = Utils.generateNextPrime(currentPrimeNo);
System.out.println("Prime Number Associated with this thread is: " + currentPrimeNo);
System.out.println("Completed process id: " + id);
}
}
And the main class is:
public class MainClass {
#SuppressWarnings("resource")
public static void main(String[] args) {
System.out.println("****This is where the project starts*****");
Scanner reader = new Scanner(System.in);
System.out.print("Enter number of processes you want to create: ");
int n = reader.nextInt();
ExecutorService executor = Executors.newFixedThreadPool(n);
for(int i=1;i<=n; i++) {
executor.submit(new Processor(i));
}
executor.shutdown();
try {
executor.awaitTermination(10, TimeUnit.MINUTES);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("****This is where the project ends*****");
}
}
Below is the generateNextPrime method from Util class:
public synchronized static int generateNextPrime(int currentPrime) {
int nextPrime = 2;
if (currentPrime <= 1) {
return nextPrime;
} else {
for (int i = currentPrime + 1;; i++) {
boolean notPrime = false;
for (int j = 2; j < i; j++) {
if (i % j == 0) {
notPrime = true;
break;
}
}
if (notPrime == false) {
return i;
}
}
}
}
Below is the output I am getting:
****This is where the project starts*****
Enter number of processes you want to create: 4
Starting process id: 2
Starting process id: 3
Starting process id: 1
Starting process id: 4
Prime Number Associated with this thread is: 2
Prime Number Associated with this thread is: 2
Completed process id: 4
Completed process id: 1
Prime Number Associated with this thread is: 2
Completed process id: 2
Prime Number Associated with this thread is: 2
Completed process id: 3
****This is where the project ends*****
Since you have not shared the code for generateNextPrime here, it would be a bit difficult to point out where exactly the code is failing.
There is an inherent problem associated with this.
Edit after Util.generateNextPrime() was added.
When we use volatile keyword, all threads would see the current value and not the cached value of the variable. But in your code, volatile variable is defined inside Runnable implementation. Thus, it doesn't server for the purpose. It is true that run method calls generateNextPrime and passes the volatile variable but what the called method actually sees and works on is a copy of the variable and not the exact variable (reading more on pass by value vs pass by reference will be beneficial to understand this better). The aim here is to have a single variable whose value should be altered by the generateNextPrime call which will be done by each thread while running.
I moved the currentPrimeNo definition to Util class so that all threads see only one variable (and not a copy of it) and that too the real-time value of the volatile variable. The method generateNextPrime() was also altered a bit for sake of compactness. The output necessarily need not be in same order as you will not know the order of invocation of the worker threads.
Here is the code:
public class Processor implements Runnable {
private int id;
public Processor(int id) {
this.id = id;
}
#Override
public void run() {
System.out.println("Starting process id: " + id);
int currentPrimeNo = Utils.generateNextPrime();
System.out.println("Prime Number Associated with this thread " + id +" is: " + currentPrimeNo);
System.out.println("Completed process id: " + id);
}
}
public class Utils {
private static volatile int currentPrime = 0;
public static synchronized int generateNextPrime(){
currentPrime++;
if(currentPrime < 2){
currentPrime = 2;
return currentPrime;
}
for (int i = 2; i <currentPrime; i++) {
if(currentPrime%i == 0) {
currentPrime++;
i=2;
} else{
continue;
}
}
return currentPrime;
}
}
Output seen while benchtesting
Sample 1:
****This is where the project starts*****
Enter number of processes you want to create: 4
Starting process id: 3
Starting process id: 1
Starting process id: 2
Starting process id: 4
Prime Number Associated with this thread 3 is: 2
Prime Number Associated with this thread 1 is: 7
Completed process id: 1
Prime Number Associated with this thread 2 is: 3
Completed process id: 2
Prime Number Associated with this thread 4 is: 5
Completed process id: 3
Completed process id: 4
****This is where the project ends*****
Sample 2:
****This is where the project starts*****
Enter number of processes you want to create: 6
Starting process id: 5
Starting process id: 1
Starting process id: 3
Starting process id: 2
Starting process id: 4
Prime Number Associated with this thread 2 is: 7
Prime Number Associated with this thread 4 is: 11
Completed process id: 4
Prime Number Associated with this thread 1 is: 3
Completed process id: 1
Prime Number Associated with this thread 5 is: 5
Completed process id: 5
Prime Number Associated with this thread 3 is: 2
Starting process id: 6
Completed process id: 2
Prime Number Associated with this thread 6 is: 13
Completed process id: 6
Completed process id: 3
****This is where the project ends*****
After clarifying the problem:
a) getting zero as a result - well in fact it is not the case, I have actually run the code this time :) It returns total randomish result as expected, depending on the number of threads created. (Note that you use threads, not processes.)
The reason for randomish result is that each thread instance starts from the value set by other thread instances. As execution order is not deterministic, the output is not deterministic either.
b) not getting prime numbers generated one after the another - this is because the calculation starts with multiple threads at the same time, and those threads work in parallel (that's what the pooled executor does).
To force all your tasks running sequentially, use a newSingleThreadExecutor.
// final ExecutorService executor = Executors.newFixedThreadPool(n); // this uses a pool
final ExecutorService executor = Executors.newSingleThreadExecutor(); // this is sequential
public static void main(String[] args) throws InterruptedException {
System.out.println("****This is where the project starts*****");
final Scanner reader = new Scanner(System.in);
System.out.print("Enter number of processes you want to create: ");
final int n = reader.nextInt();
// final ExecutorService executor = Executors.newFixedThreadPool(n); // this uses a pool
final ExecutorService executor = Executors.newSingleThreadExecutor(); // this uses a single thread
for(int i=1;i<=n; i++) {
executor.submit(new Processor(i));
}
executor.awaitTermination(10, TimeUnit.MINUTES);
System.out.println("****This is where the project ends*****");
}
The expected output is produced as:
****This is where the project starts***** Enter number of processes you want to create: 10 Starting process id: 1 Prime Number Associated
with this thread is: 2 Completed process id: 1 Starting process id: 2
Prime Number Associated with this thread is: 3 Completed process id: 2
Starting process id: 3 Prime Number Associated with this thread is: 5
Completed process id: 3 Starting process id: 4 Prime Number Associated
with this thread is: 7 Completed process id: 4 Starting process id: 5
Prime Number Associated with this thread is: 11 Completed process id:
5 Starting process id: 6 Prime Number Associated with this thread is:
13 Completed process id: 6 Starting process id: 7 Prime Number
Associated with this thread is: 17 Completed process id: 7 Starting
process id: 8 Prime Number Associated with this thread is: 19
Completed process id: 8 Starting process id: 9 Prime Number Associated
with this thread is: 23 Completed process id: 9 Starting process id:
10 Prime Number Associated with this thread is: 29 Completed process
id: 10
Note that as the execution is actually serialized, you will have no performance gain by using an executor (or separate execution threads) here.
The best problems which can benefit from parallel execution are problems where the inputs can be splitted, then processed by multiple threads in parallel, and finally composed back again. For example, converting a bitmap picture to black-and-white is a good problem for parallel execution, as the bitmap can be sliced into 8 pieces, and these pieces fed to 8 threads running in parallel. Finally once all threads are completed, the code can assembly the output to one picture, and benefit from the 8x faster execution.
When looking at the output, you can see that all 4 threads start before any computation. The prime number is calculated right after a thread starts, so it's very likely that all threads start with the same starting prime number (0), so finishes with the same ending number (2). As a result, the output you got makes sense.
The biggest problem with your code is that you execute computations in parallel, but expect the results in sequence. To achieve an output as you want, you can wrap the Utils.generateNextPrime(currentPrimeNo) method invocation in a synchronized block. This will make sure only one thread can take action on the prime value at a time.
Update 1: This is the output I got when running your code:
****This is where the project starts*****
Enter number of processes you want to create: 4
Starting process id: 2
Prime Number Associated with this thread is: 2
Completed process id: 2
Starting process id: 1
Prime Number Associated with this thread is: 3
Completed process id: 1
Starting process id: 4
Prime Number Associated with this thread is: 5
Completed process id: 4
Starting process id: 3
Prime Number Associated with this thread is: 7
Completed process id: 3
****This is where the project ends*****
Update 2: You can also change your Processor class like the following, without synchronizing the generateNextPrime method:
public class Processor implements Runnable {
private static Object lock = new Object();
private int id;
private static volatile int currentPrimeNo = 0;
public Processor(int id) {
this.id = id;
}
#Override
public void run() {
System.out.println("Starting process id: " + id);
synchronized (lock) {
currentPrimeNo = generateNextPrime(currentPrimeNo);
}
System.out.println("Prime Number Associated with this thread is: " + currentPrimeNo);
System.out.println("Completed process id: " + id);
}
}
I am working on a Enterprise application. I am facing some issues while running application in multithreaded environment. I am writing a program in which there is a variable whose value is getting updated(incremented) at very fast rate (for example 10000 updates/persecond). A loop runs for certain iterations and the value of the variable is incremented and stored in HashMap. Once the loop terminates and value the variable in HashMap is printed. I am getting unexpected value of the variable.
Here is demo program (Please read comments for better understanding) :
class test implements Runnable {
static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
static AtomicInteger value_to_be_incremented_stored = new AtomicInteger(0); // variable whose value to be updated
static AtomicInteger i = new AtomicInteger(0); // this runs the loop
#Override
public void run() {
for (i.set(0); i.get() < 100000; i.incrementAndGet()) {
/*
This loop should run 100000 times and when loop terminates according to me value of variable
"value_to_be_incremented_stored" should be 100000 as its value is incremented
100000 times the loop also runs 100000 times.
*/
System.out.println("Thread > " + Thread.currentThread() + " " + value_to_be_incremented_stored.incrementAndGet());
map.put("TC", value_to_be_incremented_stored.intValue());
}
System.out.println("Output by Thread " + Thread.currentThread() + " " + map.toString());
}
public static void main(String[] args) {
test t1 = new test();
Thread thread1 = new Thread(t1);
thread1.setName("Thread 1");
Thread thread2 = new Thread(t1);
thread2.setName("Thread 2");
Thread thread3 = new Thread(t1);
thread3.setName("Thread 3");
Thread thread4 = new Thread(t1);
thread4.setName("Thread 4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
Output (it varies) :
Issue :
I am running loop for 100000 times (i.get() < 100000) then how come value of variable value_to_be_incremented_stored becomes more than 100000.
I found three defects. One there is a race condition in the for loop between the point where you compare the loop counter, and where you increment it. You should do this in one step to get an atomic operation:
for ( ; i.incrementAndGet() < 100000; ) {
The other is there is also a race condition between the increment of your counter, and placing it in the map. Even though you increment these in series, any thread could be have a different value internally (it's at a different point in the loop) and it could put a previous value in the global map. You need atomicity here to to make sure the value you increment is the value you place in the loop.
synchronized( lock ) {
value_to_be_incremented_stored.incrementAndGet();
map.put("TC", value_to_be_incremented_stored.intValue());
}
Finally for some reason the < comparison produces a value of 99999 for me. I had to use <= to fix it.
(And as we discussed in the comments, setting i.set(0) at the start of each for loop doesn't work for fairly obvious reasons. Four defects, I guess.)
class ThreadTestX implements Runnable {
static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
static AtomicInteger value_to_be_incremented_stored = new AtomicInteger(0); // variable whose value to be updated
static AtomicInteger i = new AtomicInteger(0); // this runs the loop
static final Object lock = new Object();
#Override
public void run() {
for ( ; i.incrementAndGet() <= 100000; ) {
/*
This loop should run 100000 times and when loop terminates according to me value of variable
"value_to_be_incremented_stored" should be 100000 as its value is incremented
100000 times the loop also runs 100000 times.
*/
synchronized( lock ) {
value_to_be_incremented_stored.incrementAndGet();
// System.out.println("Thread > " + Thread.currentThread() +
// " " + value_to_be_incremented_stored.get());
map.put("TC", value_to_be_incremented_stored.intValue());
}
}
System.out.println("Output by Thread " + Thread.currentThread()
+ " " + map.toString());
}
public static void main(String[] args) {
ThreadTestX t1 = new ThreadTestX();
Thread thread1 = new Thread(t1);
thread1.setName("Thread 1");
Thread thread2 = new Thread(t1);
thread2.setName("Thread 2");
Thread thread3 = new Thread(t1);
thread3.setName("Thread 3");
Thread thread4 = new Thread(t1);
thread4.setName("Thread 4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
Output:
run:
Output by Thread Thread[Thread 4,5,main] {TC=100000}
Output by Thread Thread[Thread 3,5,main] {TC=100000}
Output by Thread Thread[Thread 1,5,main] {TC=100000}
Output by Thread Thread[Thread 2,5,main] {TC=100000}
BUILD SUCCESSFUL (total time: 0 seconds)
Afterthoughts: And in spite of getting marked correct, I'm not sure I was correct. The problem here is that you are trying to keep three things in sync: the loop counter i, the value to be incremented, and the map. Allowing any of these to be executed outside of a synchronized block may invite them to be in an unexpected state. I think the following may be safer:
#Override
public void run() {
for ( ;; ) {
synchronized( lock ) {
if( i.incrementAndGet() <= 100000 ) {
value_to_be_incremented_stored.incrementAndGet();
map.put("TC", value_to_be_incremented_stored.intValue());
}
else
break;
}
}
System.out.println("Output by Thread " + Thread.currentThread()
+ " " + map.toString());
}
This removes the need for declaring the variables as AtomicInteger, but I don't see how else you ensure that their values don't change (due to some other thread) as that loop executes.
Your "demo program" suffers from two simultaneous defects.
Defect #1 is the i.set( 0 ) pointed out by tsolakp. You say you fixed that but you are still getting a value of more than 100000. I also tried it and indeed, the final value is still larger than 100000.
I modified the program to be able to create an arbitrary number of threads, and I tried with 3, 10, and 20 threads. I got a final number of 100003, 100009, and 100019 respectively. See a pattern? So:
Defect #2 is that on the last iteration, when the value of i is 99999, the expression i.get() < 100000 is true for all threads, so all threads proceed to execute once more. The i.incrementAndGet() clause is visually sitting right next to i.get() < 1000000; but it does not get executed until the end of the loop.
So, all threads get a chance to increment i once more after the last iteration.
Everytime a new thread enters the run method it will reset your i count to zero via the first statement in the for loop by calling i.set(0).
Update: Next step after fixing reset issue, is to step through the code and see how the threads will behave.
Lets say three threads get inside the for loop while the fourth thread increments i. What will happen is that value_to_be_incremented_stored will increment 3 times and i only one time.
and this a normal thread program
class Counter implements Runnable {
private int currentValue;
public Counter() { currentValue = 0; }
public int getValue() { return currentValue; }
public void run() { // (1) Thread entry point
try {
while (currentValue < 5) {
System.out.println(Thread.currentThread().getName() + ": " + (currentValue++)); // (2) Print thread name.
Thread.sleep(250); // (3) Current thread sleeps.
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " interrupted.");
}
System.out.println("Exit from thread: " + Thread.currentThread().getName());
}
}
//_______________________________________________________________________________
public class Client {
public static void main(String[] args) {
Counter counterA = new Counter(); // (4) Create a counter.
Thread worker = new Thread(counterA, "Counter A");// (5) Create a new thread.
System.out.println(worker);
worker.start(); // (6) Start the thread.
try {
int val;
do {
val = counterA.getValue(); // (7) Access the counter value.
System.out.println("Counter value read by " + Thread.currentThread().getName()+ ": " + val); // (8) Print thread name.
Thread.sleep(1000); // (9) Current thread sleeps.
} while (val < 5);
} catch (InterruptedException e) {
System.out.println("The main thread is interrupted.");
}
System.out.println("Exit from main() method.");
}
}
and the output is
Thread[Counter A,5,main]
Counter value read by main thread: 0
Counter A: 0
Counter A: 1
Counter A: 2
Counter A: 3
Counter value read by main thread: 4
Counter A: 4
Exit from thread: Counter A
Counter value read by main thread: 5
Exit from main() method.
My question is even though the worker thread was started initially before the Main thread enters it's try block, Main thread execution starts first and then when the Main thread goes to sleep child thread gets into action.
As this picture(taken from "A Programmer's Guide To Java SCJP Certification : A Comprehensive Primer 3rd Edition"
Author: Khalid A Mughal, Rolf W Rasmussen) depicts that when the start method is called on the thread it returns immediately.
Please explain this point that why on invoking start method it return immediately and does the thread get starts on calling the start method. As here on calling the start method it doesn't invoke run method of the class. So when does actually the thread starts ?
Also explain this " the call to the start() method is asynchronous."
there are three things that you are missing in your overall analysis.
Call to thread's start method is sequential not parallel. Its the call to run method of Thread that is concurrent. So if you have 5 statements in main method that call start, the 5ht is not going t be called first. Thats the 'happens before' guarantee that JVM specs give you. However the run method of 1 first may get called before or after the call to the second start statement. This depends as its more of a CPU time slicing issue rather than program execution.
When more than 1 thread runs in your program the order of output is in-deterministic. That's because they run in parallel. You can never be sure that the same program will run in same order on two machines or even in two runs on the same machine. In your question you have posted only 1 output. Run the program like 20 times one after another and match the output. I am sure 2 or 3 would be entirely different.
Finally, you are basing your analysis on the order or execution of your concurrent code. That's the biggest blooper programmer make. Concurrent programs are never intended to run in a specific order or sequence. Just try to make your Runnable work an atomic mutually exclusive task (mutually exclusive to the rest of program or even to other Runnables) and track its own execution. Dont mix Threads together.
You cannot directly enforce which Thread is executed/running when. Once you start it, it's handled on lower level(usually by OS) and the results may differ on different machine or even in different execution. If you need more control, you need to use some synchronization mechanism.
The thread is isn't started synchronously underneath the call to start(). It happens later (asynchronously). In other words, just because you called start() doesn't mean the thread has started.
They why and how are all implementation details, that may depend on JVM and/or OS implementations.
so i was testing with synchronized keyword. Here is an example that I tried:
public class MyTest {
static int i = 0;
public static void main(String[] args) {
new Thread(t1).start();
new Thread(t2).start();
}
private static void countMe(String name){
i++;
System.out.println("Current Counter is: " + i + ", updated by: " + name);
}
private static Runnable t1 = new Runnable() {
public void run() {
try{
for(int i=0; i<5; i++){
countMe("t1");
}
} catch (Exception e){}
}
};
private static Runnable t2 = new Runnable() {
public void run() {
try{
for(int i=0; i<5; i++){
countMe("t2");
}
} catch (Exception e){}
}
};
}
When I run it, the output of calling countMe() method from two threads generates this output:
Current Counter is: 1
Current Counter is: 2
Current Counter is: 4
Current Counter is: 5
Current Counter is: 6
Current Counter is: 7
Current Counter is: 3
Current Counter is: 8
Current Counter is: 9
Current Counter is: 10
And when I change the method countMe() to:
private synchronized static void countMe(){
i++;
System.out.println("Current Counter is: " + i);
}
I get this output:
Current Counter is: 1
Current Counter is: 2
Current Counter is: 3
Current Counter is: 4
Current Counter is: 5
Current Counter is: 6
Current Counter is: 7
Current Counter is: 8
Current Counter is: 9
Current Counter is: 10
Although this gives me clear understanding the purpose of synchronized, I want to know is there any other reason as well, that we can use synchronized. Or what I have done here, is the only eason why we need the use of this synchronized keyword?
Thanks.
EDIT: Another thing that I am confused with is that in first output why the counter went to 3 after 7. It seems a bit impossible to me, but similar results do happen every time I try, is this normal?
Two things:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods. (An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed).
source: http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Vulkanino gave a good answer to your main question, so I'll only address your question about 3 printing after 7.
The 3 can print after the 7 because there is actually a lot more byte code in your statements than Java code.
I'll expand on that.
You call
System.out.println("Current Counter is: " + i);
and it occurs in one line of Java code, but really what happens is a string is created and then that string is passed to println. The println method itself has to do a bit of processing before it actually writes the line to the console.
Conceptually, something like the following is happening.
String printlnString = "Current Counter is: 3"
--> maybe the other thread executes here
System.out.println(printlnString);
--> or maybe the other thread executes here
i is now equal to 7 and the console has "Current Counter is: 7"
println writes "Current Counter is: 3" to console