I am trying to understand how java threads works with CPU cores. I have a 4 core CPU and when I try to run below codes execution times are interesting. Why it doesn't speed up with multiple threads? Am I doing something wrong?
availableProcessors() returns 4 by the way.
Below code takes nearly 27 seconds;
Runnable runnable = new Runnable() {
#Override
public void run() {
int x = 0;
while(x < 10000000){
System.out.println(x);
x++;
}
}
};
Thread t1 = new Thread(runnable);
t1.start();
When I use multiple threads it takes 33 seconds;
Runnable runnable = new Runnable() {
#Override
public void run() {
int x = 0;
while(x < 5000000){
System.out.println(x);
x++;
}
}
};
Runnable runnable2 = new Runnable() {
#Override
public void run() {
int x = 5000000;
while(x < 10000000){
System.out.println(x);
x++;
}
}
};
Thread t1 = new Thread(runnable);
t1.start();
Thread t2 = new Thread(runnable2);
t2.start();
Your program has a sequential bottleneck which is printing to the terminal.
System.out.println has a synchronized block in it and hence writes are one at a time, and hence your code is not parallel.
Sequential parts (including coordination) of the program is what governs its performance according to Amdahl's law
Related
I've already read a great number of articles where is said that AtomicInteger class works faster than a synchronize construction. I did some tests on AtomicInteger and "synchronized" and in my tests, it occurs that synchronized is much faster than AtomicInteger. I would like to understand what is going wrong: my test class is incorrect or AtomicInteger works faster in other situations?
Here is my test class:
public class Main {
public static void main(String[] args) throws InterruptedException
{
// creating tester "synchronized" class
TesterSynchronized testSyn = new TesterSynchronized();
// Creating 3 threads
Thread thread1 = new Thread(testSyn);
Thread thread2 = new Thread(testSyn);
Thread thread3 = new Thread(testSyn);
// start time
long beforeSyn = System.currentTimeMillis();
// start
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();
long afterSyn = System.currentTimeMillis();
long delta = afterSyn - beforeSyn;
System.out.println("Test synchronized: " + delta + " ms");
// _______________________________________________________
// creating tester "atomicInteger" class
TesterAtomicInteger testAtomic = new TesterAtomicInteger();
thread1 = new Thread(testAtomic);
thread2 = new Thread(testAtomic);
thread3 = new Thread(testAtomic);
// start time
long beforeAtomic = System.currentTimeMillis();
// start
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();
long afterAtomic = System.currentTimeMillis();
long deltaAtomic = afterAtomic - beforeAtomic;
System.out.println("Test atomic integer: " + deltaAtomic + " ms");
}
}
// Synchronized tester
class TesterSynchronized implements Runnable {
public int integerValue = 0;
public synchronized void run() {
for (int i = 0; i < 1_000_000; i++)
integerValue++;
}
}
// AtomicInteger class tester
class TesterAtomicInteger implements Runnable {
AtomicInteger atomicInteger = new AtomicInteger(0);
public void run() {
for (int i = 0; i < 1_000_000; i++)
atomicInteger.incrementAndGet();
}
}
Test parameters: 3 threads and 1_000_000 increments;
Result:
Test synchronized: 7 ms. Test atomic integer: 51 ms
I would be glad to understand why this is happening.
UPD
The test will be correct if change the synchronized method to a synchronized block.
// Synchronized tester
class TesterSynchronized implements Runnable {
public int integerValue = 0;
public void run() {
for (int i = 0; i < 1_000_000; i++) {
synchronized (this) {
integerValue++;
}
}
}
}
The obvious difference in your code is that the AtomicIntger version allows interleaving of threads with ever access, whereas the synchronized version does the entire loop each thread in turn.
There may be other issues. For instance, the JVM may merge multiple invocations of a synchronized block. Depending on the platform, incrementAndGet may not be an atomic operation but implemented as a CAS-loop - if contention is high that could be a problem (I am not entirely sure on that).
Whichever way it is arranged, if you have multiple threads concurrently modifying the same memory location it will not be fast.
I'd like to keep a counter of executed threads, to use in the same threads that I am executing.
The problem here is that although the counter increases, it increases unevenly and from the console output I got this (I have a for loop that executes 5 threads with ExecutorService):
This is a test. N:3
This is a test. N:4
This is a test. N:4
This is a test. N:4
This is a test. N:4
As you can see instead of getting 1,2,3,4,5 I got 3,4,4,4,4.
I assume this is because the for loop is running fast enough to execute the threads, and the threads are fast enough to execute the code requesting for the counter faster than the counter can update itself (does that even make sense?).
Here is the code (it is smaller and there is no meaningful use for the counter):
for (int i = 0; i < 5; i++)
{
Thread thread;
thread = new Thread()
{
public void run()
{
System.out.println("This is test. N: "+aldo );
//In here there is much more stuff, saying it because it might slow down the execution (if that is the culprit?)
return;
}
};
threadList.add(thread);
}
//later
for (int i = 0; i < threadList.size(); i++)
{
executor.execute(threadList.get(i));
aldo = aldo + 1;
}
executor.shutdown();
try
{
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
catch (InterruptedException e)
{
}
Yes, aldo the counter ( with a few other lists, I think) are missing from the code (they are very simple).
The best way I know of doing this is by creating a custom thread class with a constructor that passes in a number. The variable holding the number can then be used later for any needed logging. Here is the code I came up with.
public static void main(String[] args) {
class NumberedThread implements Runnable {
private final int number;
public NumberedThread(int number) {
this.number = number;
}
#Override
public void run() {
System.out.println("This is test. N: " + number);
}
}
List<Thread> threadList = new ArrayList<>();
for (int i = 1; i < 6; i++) threadList.add(new Thread(new NumberedThread(i)));
ExecutorService executor = Executors.newFixedThreadPool(10);;
for (Thread thread : threadList) executor.execute(thread);
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
catch (InterruptedException ignored) { }
}
You could also use a string object instead if you wanted to name the threads.
aldo is not modified by the tasks in the thread, but instead is modified in the main thread, here:
for (int i = 0; i < threadList.size(); i++) {
executor.execute(threadList.get(i));
//here...
aldo = aldo + 1;
}
Also, since you want a counter that can increase its value in several threads, then you may use an AtomicInteger rather than int.
Your code should look like this:
AtomicInteger aldo = new AtomicInteger(1);
for (int i = 0; i < 5; i++) {
executor.execute( () -> {
System.out.println("This is test. N: " + aldo.getAndIncrement());
});
}
Am new to java programming and first time using countDown in java,
My code snippet is,
CountDownLatch latch=new CountDownLatch(rows*columns); //rows -2 , columns -3
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
GUIView view = getView(1, 1);
if(view == null) {
if(ViewColumn(j +1) != null){
latch.countDown(); //EDT
continue;
}
latch.countDown(); //EDT
break;
}
new Thread(new countDownThread(view,latch)).start(); //Where i do some other processing and do countDown
}
}
try {
logger.log("Before countdown await");
latch.await();
logger.log("After countdown await");
}
.........
........
As i read from another post,
One of the disadvantages/advantages of CountDownLatch is that its not
reusable once count reaches to zero you can not use CountDownLatch any
more.
My doubt here is am using the same instance latch , inside the for loop. if CountDownLatch is not reusable what will happen if the first iteration latch.countDown() starts and it became zero by third iteration(The latch.countDown() at third iteration is not valid??).
The problem is :
When i debug the for loop(using eclipse), and when control reaches latch.await(); it just hangs. However, if i just run the application no hang happens.
I don't quite understand usage of countDown latch. Please explain me on the same.
Seems here you don't use multithreading, and all work done in one thread, because of you needn't to use CountDownLatch.
Also latch.await(); hang because it waiting for all count of tasks will be done(seems here it //rows -2 , columns -3 = 6) and call latch.countDown();. Read more about in docs.
Here is simple example of use, where t2 wait for t1:
import java.util.concurrent.CountDownLatch;
public class Test {
public static void main(String... s){
final CountDownLatch cdl = new CountDownLatch(1);
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
int i = 5;
while(i-- > 0)
System.out.println("t2 wait me");
cdl.countDown();
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("done");
}
});
t2.start();
t1.start();
}
}
When you initialize CountDownLatch with some value for example:
CountDownLatch latch = new CountDownLatch(3);
It basically means that when method:
latch.countDown();
will be fired three times, the class which will use latch will be released from the await method call.
Of course you must ensure that the same instance of latch is used.
For more information go to nice tutorial: http://tutorials.jenkov.com/java-util-concurrent/countdownlatch.html
I have a requirement in which 28 threads have to complete some functionality. I have created these threads as in anonymous inner classes like :
Thread t=new Thread(new Runnable(){public void run()
{//code
}}
);
t.start();
Now I want that the further execution should start after all these threads have finished there work.
Note : I am confused about join() method as it makes my threads run sequentially.
So can anyone suggest me how can I make main thread run once these threads are done with work.
Note : I am confused about join() method as it makes my threads run sequentially.
It will do that if you have code like this:
for (Runnable runnable : runnables) {
Thread t = new Thread(runnable);
t.start();
t.join();
}
However, you can start all the threads you want to run in parallel, then call join on them all. For example:
List<Thread> threads = new ArrayList<>();
for (Runnable runnable : runnables) {
Thread t = new Thread(runnable);
t.start();
threads.add(t);
}
// Now everything's running - join all the threads
for (Thread thread : threads) {
thread.join();
}
// Now you can do whatever you need to after all the
// threads have finished.
There are many other approaches, of course - starting threads directly may well not be as suitable in your code as using a higher level abstraction; it depends on what you're trying to achieve. The above should work fine though - assuming all the Runnables are able to run in parallel without blocking each other through synchronization.
Make use of CountDownLatch.
public static void main(String... args) {
final CountDownLatch latch = new CountDownLatch(28);
for(int i=0;i<28;i++) {
Thread t=new Thread(new Runnable(){
public void run()
{
try {
//code
} finally {
latch.countDown();
}
}
});
t.start();
}
latch.await();
// Continue Code
}
Use a CountDownLatch and wait for all your threads to complete. :) .
PS : I gotto agree, using join() is also correct and more efficient.
example code :
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("t1 : " + i);
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("t2 : " + i);
}
}
});
t2.start();
t1.join();
t2.join();
System.out.println("main");
}
O/P :
t1 : 0
t1 : 1
t2 : 0
t1 : 2
t1 : 3
t2 : 1
t1 : 4
t1 : 5
t2 : 2
t1 : 6
t1 : 7
t2 : 3
t1 : 8
t1 : 9
t2 : 4
t2 : 5
t2 : 6
t2 : 7
t2 : 8
t2 : 9
main
According to the behaviour you're giving for join, I'm guessing you're starting and joining the threads within a single loop.
If you check the javadoc on this page, you'll note that a call to join will halt the execution of the calling thread until the other thread has finished executing.
You might want to keep an array or a list of threads when creating them, and starting them all in one loop, and only then joining them all.
Thread[] workers = new Thread[28];
for (int i = 0; i < workers.length; i++) {
workers[i] = new Thread { ... };
}
// Start running all threads
for (Thread worker: workers) {
worker.start();
}
// Make sure all threads are completed
for (Thread worker: workers) {
worker.join(); // if the worker already stopped, it'll return immediately.
}
// Now all threads have finished running and you can start post-processing
It's not the most elegant solution, but it'll do the trick.
As mentioned by others, you should probably use a CountDownLatch (haven't used one yet, so I can't provide feedback)
Edit: I've been beaten to it by Jon Skeet, sorry for the redundant answer...
CountDownLatch is better option.
I have created dummy program.
In this program I am sum 1000 number. I created 10 thread. In main thread I am doing dome of all child thread sum. you will get understand to simply viewing the code.
package Test1;
import java.util.concurrent.CountDownLatch;
class Sum extends Thread {
private int from;
private int to;
private int sum = 0;
CountDownLatch latch;
public int getSum() {
return sum;
}
public Sum(int from, int to, CountDownLatch latch) {
this.from = from;
this.to = to;
this.latch = latch;
}
public void run() {
for (int i = from; i < to; i++) {
sum += i;
}
latch.countDown();
}
}
public class Test5 {
public static void main(String[] args) throws InterruptedException {
int n = 1000;
int tn = 10;
int from = 1;
int to;
int sum = 0;
Sum[] sumArray = new Sum[tn];
final CountDownLatch latch = new CountDownLatch(tn);
for (int i = 0; i < tn; i++) {
to = from + n / tn;
Sum s = new Sum(from, to, latch);
sumArray[i] = s;
s.start();
from = to;
}
// Thread.sleep(1000);
latch.await();
for (int i = 0; i < tn; i++) {
sum += sumArray[i].getSum();
}
System.out.println(sum);
}
}
I need two threads to write one a shared array of ints. Both threads need to write on all the elements of that array. Each thread will write either 1 or 7, and the result should be like 171717171 (or 71717171). To do that I have the first Thread1 write at position 0, then wait. Thread2 now writes at position 0 and 1, notifies Thread1, and waits. Thread1 writes at position 1 and 2, notifies Thread2 and waits, etc. With the following code I get correct output, although when run with JPF it finds a deadlock. Its become really frustrating since I can not find whats wrong with it. Any advice would be appreciated.
import java.util.logging.Level;
import java.util.logging.Logger;
public class WriterThreadManager {
private int[] array = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
private Thread thread7;
private Thread thread1;
public static void main(String[] args) {
WriterThreadManager mng = new WriterThreadManager();
mng.exec();
}
public WriterThreadManager() {
thread7 = new Thread(new WriterRunnable(this, 7));
thread1 = new Thread(new WriterRunnable(this, 1));
}
public void overwriteArray(int pos, int num) {
array[pos] = num;
printArray();
}
private void printArray() {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]);
}
System.out.println("");
}
public synchronized void stopThread() {
try {
this.wait();
} catch (InterruptedException ex) {
Logger.getLogger(WriterThreadManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
public synchronized void wakeUpThread() {
notifyAll();
}
private void exec() {
thread7.start();
thread1.start();
}
public int length() {
return array.length;
}
}
public class WriterRunnable implements Runnable {
private WriterThreadManager mng;
private int numberToWrite;
private static boolean flag = true;
#Override
public void run() {
int counter = 0;
int j = 0;
//first thread to get in should write only at
//position 0 and then wait.
synchronized (mng) {
if (flag) {
flag = false;
mng.overwriteArray(0, numberToWrite);
j = 1;
waitForOtherThread();
}
}
for (int i = j; i < mng.length(); i++) {
mng.overwriteArray(i, numberToWrite);
counter++;
if (i == mng.length() - 1) {
mng.wakeUpThread();
break;
}
if (counter == 2) {
waitForOtherThread();
counter = 0;
}
}
}
private void waitForOtherThread() {
mng.wakeUpThread();
mng.stopThread();
}
public WriterRunnable(WriterThreadManager ar, int num) {
mng = ar;
numberToWrite = num;
}
}
p.s: an example of the execution:
1000000000
7000000000
7700000000
7100000000
7110000000
7170000000
7177000000
7171000000
7171100000
7171700000
7171770000
7171710000
7171711000
7171717000
7171717700
7171717100
7171717110
7171717170
7171717177
7171717171
The error snapshot from JPF is the following:
thread java.lang.Thread:{id:1,name:Thread-1,status:WAITING,priority:5,lockCount:1,suspendCount:0}
waiting on: WriterThreadManager#152
call stack:
at java.lang.Object.wait(Object.java)
at WriterThreadManager.stopThread(WriterThreadManager.java:43)
at WriterRunnable.waitForOtherThread(WriterRunnable.java:53)
at WriterRunnable.run(WriterRunnable.java:45)
thread java.lang.Thread:{id:2,name:Thread-2,status:WAITING,priority:5,lockCount:1,suspendCount:0}
waiting on: WriterThreadManager#152
call stack:
at java.lang.Object.wait(Object.java)
at WriterThreadManager.stopThread(WriterThreadManager.java:43)
at WriterRunnable.waitForOtherThread(WriterRunnable.java:53)
at WriterRunnable.run(WriterRunnable.java:45)
I believe the race is due to this method:
private void waitForOtherThread() {
mng.wakeUpThread();
mng.stopThread();
}
While the individual wakeUpThread() and stopThread() methods are synchronized, you have the opportunity for unexpected thread scheduling between these calls.
Consider:
thread7 - notify thread1 to wakup
thread1 - wake up
thread1 - work to completion
thread1 - notify thread7 to wakeup
thread1 - wait to be notified to wakeup
thread7 - wait to be notified to wakeup
In this case you have deadlocked because thread1 sent its notifyAll() before thread7 had a chance to wait() for it.
Running in a different context can mess with your timing and cause these types of behaviors to appear.
To avoid this I suggestion doing this:
private void waitForOtherThread() {
synchronized(mng) {
mng.wakeUpThread();
mng.stopThread();
}
}
Or better yet, use a semaphore as #KumarVivekMitra suggested. Semaphores combine both the notification system and a counter so that the order of the notify and wait don't matter.
- I think a better approach here would be java.util.Semaphores, which will help you to decide the access over the objects resources by specific numbers of threads at a time.
- Well you can also use the SingleThreadExecutor to solve this, which starts and completes a task before moving on to the 2nd task, so there will be No need of synchronization needed here from your side.
I don't think you need any sort of coordination here. Just have one thread write the even locations and the other thread write the odd locations. Let them both go as fast as they can. Done!