cachedThreadPool not working as I expected - java

I'm playing around with threads and I don't understand why this isn't working as I thought.
I am trying to calculate a sum using threads and was expecting for the thread pool to wait for all tasks to finish by the time I print out the result (due to the shutdown() call and the isTerminated() check).
What am I missing here?
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test5 {
private Integer sum= new Integer(0);
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
Test5 obj = new Test5();
for(int i=0; i<1000; i++){
pool.execute(obj.new Adding());
}
pool.shutdown();
while(!pool.isTerminated()) {
//could be empty loop...
System.out.println(" Is it done? : " + pool.isTerminated());
}
System.out.println(" Is it done? : " + pool.isTerminated());
System.out.println("Sum is " + obj.sum);
}
class Adding implements Runnable {
public void run() {
synchronized(this) {
int tmp = sum;
tmp+=1;
sum=new Integer(tmp);
}
}
}
}
While I do get good results, I also get output such as this:
Is it done? : true
Sum is 983

You need to sync on the main object instance. I'm using int below, Integer will work too (needs to initialized to zero explicitly).
Here is the working code
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AppThreadsSum {
int sum;
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
AppThreadsSum app = new AppThreadsSum();
for (int i = 0; i < 1000; i++) {
pool.execute(app.new Adding());
}
pool.shutdown();
while (!pool.isTerminated()) {
System.out.println(" Is it done? : " + pool.isTerminated());
}
System.out.println(" Is it done? : " + pool.isTerminated());
System.out.println("Sum is " + app.sum);
}
class Adding implements Runnable {
public void run() {
synchronized (AppThreadsSum.this) {
sum += 1;
}
}
}
}
p.s. Busy waiting is an anti-pattern to be avoided (copied from the neighbor answer to be complete and aware of this important thing, see comments)

You have a number of issues.
Your code is not threadsafe
Busy waiting is an anti-pattern to be avoided.
What do i mean by 1.?
Lets suppose we have two threads, A & B.
A reads sum into tmp as 1
B reads sum into tmp as 1
A increments sum to 2
A writes sum as 2
B increments sum to 2
B writes sum as 2
So we end up with 2 after two increments. No quite right.
Now you may say "but I have used synchronized, this should not happen". Well, you haven't.
When you create your Adding instances you new each one. You have 1000 separate Adding instances.
When you synchronized(this) you are synchronizing on the current instance, not across all Adding. So your synchronized block does nothing.
Now, the simple solution would be to use synchronized(Adding.class).
The synchronized(Adding.class) will make the code block synchronized correctly across all Adding instances.
The good solution would be to use an AtmoicInteger rather than an Integer as this increments atomically and is designed for exactly this sort of task.
Now onto 2.
You have a while(thing){} loop, this basically runs the thread like crazy testing thousands of times a millisecond until thing is true. This is a huge waste of CPU cycles. An ExecutorService has a special, blocking, method that waits until it has shutdown, awaitTermination.
Here is an example:
static final AtomicInteger sum = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
pool.execute(new Adding());
}
pool.shutdown();
pool.awaitTermination(1, TimeUnit.DAYS);
System.out.println(" Is it done? : " + pool.isTerminated());
System.out.println("Sum is " + sum);
}
static class Adding implements Runnable {
public void run() {
sum.addAndGet(1);
}
}
I would also suggest not using a cachedThreadPool in this circumstance as you have 1000 Runnables being submitted and this will generate far more Threads than you have CPUs. I would suggest using newFixedThreadPool with a sane number of Threads.
I'm not even going to go into the use of int literals and Integer and why new Integer() is not needed.

Related

How to ensure execution order of threads [duplicate]

This question already has answers here:
How threads are executed in the memory?
(2 answers)
Closed 2 years ago.
This is a simplified version of the problem. Given n number of threads, each printing a constant number all the time. For example, Thread-1 should always print 1, Thread-2 should always print 2 and so on...
How to ensure, the threads are executed in order i.e. the output should be as below:
Thread-1: 1
Thread-2: 2
Thread-3: 3
.
.
.
Thread-n: n
I have a naïve solution to do it through wait()/notify() but I guess there might be a better solution than that. Perhaps, using Semaphore maybe? I don't know.
Update:
Based on the answers received, I think I was not very clear. There are some constraints:
All threads should start at once (assume we don't really have control on that)
Once all the threads start, there should be some sort of communication between the threads to execute in order.
This sequentially execution of thread can be handled beautifully using Thread.join() method. To handle it properly, you may have to create MyRunnable(or, use any name you prefer) which implements Runnable interface. Inside MyRunnable, you can inject a parent Thread, and call parent.join() at top of MyRunnable.run() method. The code is given below:
public class SequentialThreadsTest {
static class MyRunnable implements Runnable {
static int objCount; // to keep count of sequential object
private int objNum;
private Thread parent; // keep track of parent thread
MyRunnable(Thread parent) {
this.parent = parent;
this.objNum = objCount + 1;
objCount += 1;
}
#Override
public void run() {
try {
if(parent != null) {
parent.join();
}
System.out.println("Thread-" + objNum + ": " + objNum);
} catch(InterruptedException e) {
e.printStackTrace();
// do something else
} finally {
// do what you need to do when thread execution is finished
}
}
}
public static void main(String[] args) {
int n = 10;
Thread parentThread = null;
for(int i=0; i<n; i++) {
Thread thread = new Thread(new MyRunnable(parentThread));
thread.start();
parentThread = thread;
}
}
}
And the output is:
Thread-1: 1
Thread-2: 2
Thread-3: 3
Thread-4: 4
Thread-5: 5
Thread-6: 6
Thread-7: 7
Thread-8: 8
Thread-9: 9
Thread-10: 10
You haven't specified many details, but if you only want serializable thread execution you can wait for previous thread to finish and then print. Something like this:
public static void main(String[] args) {
Thread thread = null;
for (int i = 0; i < 10; i++) {
int index = i;
Thread previousThread = thread;
thread = new Thread(() -> {
if (previousThread != null) {
try {
previousThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(index);
});
thread.start();
}
}
Try making a queue - this will do exactly what you want. Simply change the value of n to however many threads you have, and add all the threads sequentially (only once). If ever you want to stop the threads from executing, all you have to do is add end to the queue. Obviously, for a larger project, you will need to modify this code a little bit (I would recommend replacing the main method with a class initializer and pass the LinkedBlockingQueue as a pre-built argument)
import java.util.concurrent.LinkedBlockingQueue;
public class HelloWorld{
private static int n = 2;
private static LinkedBlockingQueue<Thread> queue = new LinkedBlockingQueue<>(n+1);
static Thread a = new Thread(()->{
System.out.print("a");
});
static Thread b = new Thread(()->{
System.out.print("b");
});
static Thread end = new Thread(()->{
break_ = true;
});
public static final int END = 20;//this and the counter are just here so the code doesn't run forever
public static volatile int i = 0;
public static volatile boolean break_ = false;
public static void main(String []args){
queue.add(a);
queue.add(b);
//queue.add(end);
outerloop:
while(true){
Thread toBeRun = queue.poll();
try{
toBeRun.run();
queue.add(toBeRun);
i++;
if(i>=END || break_){//i>=END does not need to be here, it's just to stop it from running forever in this example
break;
}
}catch(NullPointerException e){
break;
}
}
}
}
Note: This uses java 8 lambdas. If you're using an older version of java, you will need to create the threads using the run method.

Java concurrency using ConcurrentHashMap with synchronized block

Here is my main class that initializes and starts 5 different Threads:
public class Server implements Runnable {
Server1 server1;
Thread server1Thread;
public Server() {}
#Override
public void run() {
server1 = new Server1();
server1Thread = new Thread(server1);
server1Thread.start();
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Server s = new Server();
s.run();
}
}
}
Here is my Server1 Runnable:
import java.util.concurrent.ConcurrentHashMap;
public class Server1 implements Runnable {
private ConcurrentHashMap<Integer, Integer> storage= new ConcurrentHashMap<>();
public Server1() {}
#Override
public void run() {
synchronized (this){
for (int i = 0; i < 10; i++) {
storage.put(i, (int)(Math.random()*100));
}
for (int i : storage.keySet()) {
System.out.print("(" + i + "," + storage.get(i) + ") ");
}
System.out.println();
}
}
}
It puts in ConcurrentHashMap storage keys from 0 to 9 and assigns them a random value between 0 and 100. After that it prints it and prints new line at the end. I have user synchronized block to make sure the thread itself access keys correctly but it prints something like this:
(0,8) (0,87) (1,60) (1,14) (2,20) (2,70) (3,5) (0,74) (0,42) (1,22) (4,96) (0,85) (1,97) (2,75) (3,68) (4,3) (5,49) (6,3) (7,9) (8,47) (9,52)
(3,2) (5,74) (2,86) (1,48) (3,5) (6,0) (4,0) (7,86) (4,22) (8,20) (2,17) (9,87)
(5,96) (5,15) (6,15) (6,92) (7,48) (8,93) (9,67)
(3,87) (7,43) (4,34) (5,48) (8,91) (9,64)
(6,84) (7,75) (8,47) (9,87)
which obviously means that some thread prints more that 10 keys that I assigned to it. How do I make every thread print exactly 10 keys and values that it is assigned to them and ensure concurrency here?
I am not sure how to test it.
Your threads don't share any internal state. They're working fine, but the output is interleaved.
For instance if you used a StringBuilder to do the I/O in one operation, you should see correct output.
StringBuilder buff = new StringBuilder();
for (int i : storage.keySet()) {
buff.append("(" + i + "," + storage.get(i) + ") ");
}
System.out.println(buff);
There is no good reason for Server to be Runnable, or even to create any instances of it.
You do not share any of the maps. If you did, then you would also want to share a common lock, but this is not the usual way to use ConcurrentMap.
All you had to do was synchronized (Server1.class) as that is common across threads. Not the instance
Here is the verified output:
(0,75) (1,9) (2,61) (3,73) (4,55) (5,34) (6,34) (7,74) (8,41) (9,0)
(0,30) (1,42) (2,46) (3,66) (4,12) (5,17) (6,62) (7,59) (8,74) (9,4)
(0,50) (1,16) (2,29) (3,74) (4,68) (5,42) (6,33) (7,91) (8,25) (9,7)
(0,49) (1,10) (2,39) (3,94) (4,12) (5,55) (6,54) (7,89) (8,21) (9,75)
(0,77) (1,10) (2,37) (3,32) (4,73) (5,39) (6,64) (7,98) (8,96) (9,44)

Synced multithreading add 1 to number, varying results

I don't know if this is working the right way, but I'm attempting to add 1 to a variable using 1000 threads. I then print out the number at the end to verify that it worked, it never is 1000 and it also changes.
I determined this is likely a synchronization issue from googling and look on SO but when I try to sync the threads, it still isn't 1000 at the end and varies but a lot less (varies between 995 to 997 whereas without sync it varies between 900 and 1000 roughly).
Here is what I'm doing so far:
public class Main extends Thread{
public static void main(String[] args) {
Thread[] threads = new Thread[1000];
Adder adder = new Adder();
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new ThreadAddSync(adder));
threads[i].start();
}
System.out.println("----- " + adder.count);
}
}
public class ThreadAddSync implements Runnable{
Adder add;
public ThreadAddSync(Adder add){
this.add = add;
}
#Override
public void run() {
synchronized(add){
add.add();
}
}
}
public class Adder {
int count = 0;
public void add(){
count += 1;
}
}
My question is should these threads be synced the way I have this written? And if they are synced why are they producing varying results if they're technically safe?
System.out.println("----- " + adder.count); - you access count but don't synchronize on adder and thus, it is not safe (nor did you wait for the workers to complete, join() if you expect to see the final total before you print the total, or add another loop to wait). Also, in real code, you should be using AtomicInteger.

How to prevent context switch in a critical section

I have the following code :
import java.util.ArrayList;
public class main {
final static Object lock= new Object();
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) {
System.out.println("-------");
finish finished = new finish(false);
ArrayList<Boolean> arr = new ArrayList<>();
Thread t1 = new Thread(() -> {
System.out.println(Thread.currentThread().getId() + " Is setting");
finished.setFinished(true);
});
t1.start();
synchronized (lock){
if (finished.isFinished == false) {
System.out.println(Thread.currentThread().getId() + " Is adding");
arr.add(new Boolean(finished.isFinished));
} else {
System.out.println("Done");
}
}
System.out.println("The length of array is " + arr.size());
if (arr.size() > 0) {
System.out.println("The val of array is " + arr.get(0));
}
}
}
}
class finish {
public boolean isFinished = false;
public finish(boolean finished) {
this.isFinished = finished;
}
public void setFinished(boolean finished) {
this.isFinished = finished;
}
}
I am expecting to get the following output :
The length of array is 1
The val of array is false
or
Done
It is the case most of the times.
But sometimes the output is :
The length of array is 1
The val of array is true
It means, that there was a context switch in the critical section.
I have tried to synchronized the code on an object, but it did not help.
It is a classical synchronization problem, I but was not able to solve it.
Maybe I should use atomic objects, but I have no idea how would they help in this case.
Or perhaps I am to harsh with java, and I should not test it in a for loop? I am running this example on a Linux OS.
I think my synchronization does not make sense. But I don't know how to solve it.
It's not at all clear what your example code is trying to do, but if you want to wait for the thread to finish, use t1.join() and deal with the InterruptedException that this throws. Also, finished should be an AtomicBoolean if you're going to use it in more than one thread.
But all in all, the code is pretty problematic, and doesn't reflect whatever real-life scenario you're trying to deal with.
In this code you are reading the same variable twice, which allows for the possibility it can be changed. The simplest solution is to read it just once.
boolean isFinished = finished.isFinished;
if (isFinished) {
System.out.println("Done");
} else {
System.out.println(t1 + " Is adding");
arr.add(isFinished);
}

Is this multi-threading code guaranteed to always return zero?

I am taking a book to do some mock test, I have found this question:
import java.util.concurrent.atomic.AtomicInteger;
class AtomicVariableTest {
private static AtomicInteger counter = new AtomicInteger(0);
static class Decrementer extends Thread {
public void run() {
counter.decrementAndGet(); // #1
}
}
static class Incrementer extends Thread {
public void run() {
counter.incrementAndGet(); // #2
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Incrementer().start();
new Decrementer().start();
}
System.out.println(counter);
}
}
The answer:
This program will always print 0.
But I think there is no guarantee that the threads will have completed when it prints the counter value.
I mean, most of the time it will return 0, but if you are strict with the theory there is no guarantee of this.
Am I correct?
There is guaranteed. And there is not guaranteed. There is no middle ground.
In this case there is no guarantee that the result is always zero. This is because the threads are not joined - and might never even have actually ran before the print!
For example, among other permutations, the sequence this code could have executed is:
counter.decrementAndGet(); // #1
System.out.println(counter); // Main thread
counter.incrementAndGet(); // #2
// (and so on, at some arbitrary point after the print)
Avoiding such undesired interleaving/execution is handled in Java (as per the JLS) under happens-before relationships.
If the threads were joined (to the thread with the print) then a happens-before would have been established - in this case that would mean that the threads started and finished running - and the result would be guarantee to be zero.
public static void main(String[] args) {
final List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 5; i++) {
final new Incrementer i = new Incrementer();
threads.add(i);
i.start();
final new Decrementer d = new Decrementer();
threads.add(d);
d.start();
}
for (final Thread t : threads) { t.join(); }
System.out.println(counter);
}
See one of the many duplicates: Wait until child threads completed : Java
And this is why you use the ExecutorService or ExecutorCompletionService and never deal with thread management manually because it is extremely error prone otherwise.

Categories