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);
}
}
Related
I have following code :
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyThread implements Runnable{
private List<Integer> myList;
public MyThread(List<Integer> list){
this.myList = list;
}
private void updateList(int i){
synchronized (myList) {
myList.add(i);
}
}
#Override
public void run() {
for( int i = 0; i < 1000000;i++){
updateList(i);
}
System.out.println("end: " + myList.size());
}
}
public class MyExecutor {
private List<Integer> taskList = new ArrayList<>();
private void launch(){
ExecutorService executorService= Executors.newFixedThreadPool(10000);
executorService.execute(new MyThread(taskList));
executorService.execute(new MyThread(taskList));
executorService.shutdown();
}
public static void main(String[] args) {
MyExecutor test = new MyExecutor();
test.launch();
}
}
the output should be : 2000000
I will get different result which means these two threads are replacing each other's value.
I can't figure out where is the problem, tried several modifications on this code but none of them has fixed the problem. (replaced with Vector / added synchronize in constructor / added volatile)
Why doesn't this code work correctly?
Edit
At both thread I expect to get 1000000
the output should be : 2000000
No, for three reasons:
You are printing two things, so the output won't be a single number.
It prints the size when each thread happens to have added 1000000 things; you know nothing about how much the other thread has done at this point.
You are not accessing the size in a synchronized way, so you are liable to get a non-up to date value.
You are getting
end: 1065878
end: 2000000
The first line is from the thread that has finished its job first. It shouldn't be exactly 1M, because several threads are working. It's reasonable to assume that by the time one first thread finishes adding its 1M, the other has added at least one.
The second line is always 2M (as you expected ) due to the synchronised method.
I guess the first thread should execute for the exact number I wanted, no more no less.
Things happened in parallel. The threads were running. Each was trying to invoke updateList: one entered, the others waited. There was no priority on who should be next, so the control over the method was being passed among all the workers in a rather random manner.
I bet you are still thinking of the sequential execution :) One thread runs the whole run method, prints 1M, the other takes a 1M-sized list and adds its portion.
To understand it better, add a print statement
private void updateList(int i) {
synchronized (myList) {
myList.add(i);
System.out.println(Thread.currentThread().getName() + " added " + i);
}
}
and reduce the number of elements to add by a task to, let's say, 10.
pool-1-thread-1 added 0
pool-1-thread-1 added 1
pool-1-thread-1 added 2
pool-1-thread-1 added 3
pool-1-thread-2 added 0
pool-1-thread-2 added 1
pool-1-thread-2 added 2
pool-1-thread-2 added 3
pool-1-thread-1 added 4
pool-1-thread-1 added 5
pool-1-thread-1 added 6
pool-1-thread-1 added 7
pool-1-thread-1 added 8
pool-1-thread-1 added 9
end: 14
pool-1-thread-2 added 4
pool-1-thread-2 added 5
pool-1-thread-2 added 6
pool-1-thread-2 added 7
pool-1-thread-2 added 8
pool-1-thread-2 added 9
end: 20
I am trying to execute 5 threads start perfectly at same time. But looking at output of below I think they started at same time but not concurrently as the age counter always finish with 5 count. If they executed real concurrently the
age output must be same for the bunch. By real concurrently Or perfect Same time I think all 5 threads passing 1 as age and all thread prints same age not increment values. Please correct me.
public class ExecutorServiceTester {
public static void main(String args[]) throws InterruptedException {
ExecutorServiceTester tester = new ExecutorServiceTester();
tester.executeTester();
}
private void executeTester() throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(10);
Runnable worker = new MyRunnable(1);
for (int i = 0; i < 10; i++) {
executorService.execute(worker);
} executorService.shutdown();
}
public static class MyRunnable implements Runnable {
int age = 0;
public MyRunnable(int count) {
this.age = count;
}
#Override
public void run() {
System.out.println(new Timestamp(new Date().getTime())+" ThreadName:"+Thread.currentThread().getName()
+ " Age " + age++);
}
} }
OUTPUT:
2015-03-23 02:02:18.243 ThreadName:pool-1-thread-1 Age 1
2015-03-23 02:02:18.243 ThreadName:pool-1-thread-5 Age 3
2015-03-23 02:02:18.243 ThreadName:pool-1-thread-3 Age 5
2015-03-23 02:02:18.243 ThreadName:pool-1-thread-2 Age 2
2015-03-23 02:02:18.243 ThreadName:pool-1-thread-4 Age 4
While trying with Executors.newCachedThreadPool(); and increased number to 12, the OUTPUT had something of interest then
2015-03-23 02:17:57.189 **ThreadName:pool-1-thread-4 Age 1**
2015-03-23 02:17:57.189 ThreadName:pool-1-thread-10 Age 3
2015-03-23 02:17:57.189 ThreadName:pool-1-thread-12 Age 2
2015-03-23 02:17:57.189 **ThreadName:pool-1-thread-11 Age 1** ...
The reason all your threads are using the same counter is that you are feeding them the same Runnable instance. Just create a new one for each thread inside the loop instead:
for (int i = 0; i < 10; i++) {
Runnable worker = new MyRunnable(1);
executorService.execute(worker);
}
It may not be ideal, but if you need them to be perfectly aligned, I would set some type of Mark. Use System.nanoTime() to get a current time down to the nanosecond. Give it a period of time to wait, say a full second (1_000_000_000) nano seconds. Make sure the delay is long enough (whatever it is) for all threads to be initialized and get to waiting point. Pass that MarkTime to each thread on creation. Then have each thread have a function like this:
while(System.nanoTime() < MarkTime){
// do nothing
}
Boom, when time is reached, all threads are off and running, coordinated down to the nanosecond.
Is like runners getting ready at the starting line for a race. They all arrive at the line at different times, but all start at the same starters pistol shot.
Also, as #Keppil said, you probably want to create a new instance of the thread for each version, not 5 copies of the same instance. That way you can be sure they run independently, yet at the same time.
Alternatively: Another way to do so, is to set a boolean in the parent class, set it to false, after all threads are active, have them check that boolean. When all are loaded and running, change boolean to true. Same effect, but maybe with a slight drop in precision. How close do you need it?
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.
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.
I just have started learning threads and come upon misunderstanding of how they work.
Here is my class:
public class MyThread extends Thread {
private static int NUM = 0;
private int id;
public MyThread() {
id = NUM++;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new MyThread().start();
}
}
public void run() {
System.out.println(id + " started");
try {
Process p = Runtime.getRuntime().exec("javac -version");
p.waitFor();
} catch (Exception e) {
System.out.println("Call a doc!");
}
System.out.println(id + " finished");
}
}
/*
Just a sidenote.
I am creating new javac process just to slow an application down.
Simple System.out.println(…) is a way faster.
*/
Why do I always get all "… started" messages at first and after that "… finished" messages? No matter how many threads have I started, I always see:
0 started
1 started
2 started
3 started
4 started
5 started
6 started
7 started
8 started
9 started
0 finished
1 finished
3 finished
4 finished
8 finished
5 finished
2 finished
6 finished
9 finished
7 finished
Isn't the purpose of threads to parallelize execution?
Maybe I need to synchronize something? Or made careless mistake? Or…?
Explain, please.
UPDATE:
Why don't I see, let's say:
0 started
1 started
0 finished
2 started
1 finished
2 finished
Thank you all for treatment.
Looks ok. You can see from your output that the threads are interleaving. threads are getting started, get context-switched, and get picked by the scheduler, you can see where thread 8 jumps ahead of thread 5, for instance. If all the numbers were in order consistently it would be strange but this seems fine.
Use sleep time, like Peter Lawrey suggests, so you can alter how long each thread takes more easily. As your example stands, starting a process takes so much time it seems reasonable all your threads should get started before any finish.
The threads are parallel. Otherwise you would see each thread "finished" before the next one "started"
A simple way to slow down a thread is to use Thread.sleep(10*1000); to sleep for 10 seconds (10,000 milli-seconds)
EDIT: a simple way to see threads interleaving is to have a fixed size thread pool.
ExecutorService pool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
final int id = i;
pool.submit(new Callable<Void>() {
public Void call() throws InterruptedException {
System.out.println(id + " started");
Thread.sleep(1000);
System.out.println(id + " finished");
return null;
}
});
}
Prints
0 started
1 started
2 started
3 started
0 finished
4 started
1 finished
5 started
2 finished
6 started
3 finished
7 started
4 finished
8 started
5 finished
6 finished
9 started
7 finished
8 finished
9 finished
If you put a simple loop to count from 1 to 20 in the run() method you may see the interleaving of the execution better.
There is a difference between multi-threading and parallel processing... check this out...
If you want to see a "random" starting and ending you might want to add a
Thread.sleep(new Random().nextInt(1000));
or similar to the threads.