I'm trying to get started with learning threading in Java and here's a simple example that I tried from here
Here's my code :
A simple main class:
package com.vogella.Thread;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// We will store the threads so that we can check if they are done
List<Thread> threads = new ArrayList<Thread>();
// We will create 500 threads
for (int i = 0; i < 500; i++) {
Runnable task = new MyRunnable(10000000L + i);
Thread worker = new Thread(task);
// We can set the name of the thread
worker.setName(String.valueOf(i));
// Start the thread, never call method run() direct
worker.start();
// Remember the thread for later usage
threads.add(worker);
}
int running = 0;
do {
running = 0;
for (Thread thread : threads) {
if (thread.isAlive()) {
running++;
}
}
System.out.println("We have " + running + " running threads. ");//-A
} while (running > 0);
}
}
and the MyRunnable class is as follows :
package com.vogella.Thread;
public class MyRunnable implements Runnable {
private final long countUntil;
MyRunnable(long countUntil) {
this.countUntil = countUntil;
}
#Override
public void run() {
long sum = 0;
for (long i = 1; i < countUntil; i++) {
sum += i;
}
System.out.println(sum);
System.out.println("Test123");
}
}
And this is my output
49999995000000
Test123
50000005000000
Test123
50000015000001
Test123...
However I dont understand why the line marked with comment A in Main.java never prints. Any insight on this would be helpful.
Thanks!
It should print. Check you're not missing it in the program output.
Try commenting out the println()'s in your Runnable
There are a few things wrong with that code in terms of best practices. Unless that site mentions them (too lazy to look), I might consider finding a different tutorial. Also, have you checked the entire output? It's probably printing. It is not guaranteed to print as the last thing as I am going to guess you're assuming.
It should be able to print something. A few ideas for testing:
comment the println statements in your runnable - maybe it gets printed but you don't see it because there's too much output on the console
add a System.println(threads.size()) before the do statement to see how many threads have been added (should print 500).
add a Thread.sleep(100) before the do statement. Maybe the first thread gets alive after the do-while block has finished...
Related
In one of the interview, a coding question was asked to me and I had to find the problem in that code and suggest proper solution.
Please find below the entire code:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Atomic {
static AtomicInteger count = new AtomicInteger(0);
static int counter = 0;
public static class Runnable extends Thread {
public void run() {
while (count.getAndSet(1) != 0) {
try {
Thread.sleep(3000);
} catch (Exception e) {
}
}
counter = counter + 1;
count.set(0);
}
}
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
Runnable runnable = new Runnable();
executor.execute(runnable);
}
executor.shutdown();
}
}
This code is running properly. But question is , there is some problem in this code if number of threads get increased or if I run For loop for almost 10000 times.
I tried to find the problem, but couldn't find one.
There are several things wrong with this code. You've not stated with "there is some problem" means, but here are the things that jump out.
Firstly, the counter variable is not updated safely. Multiple threads don't have guaranteed visibility of the last-written value; nor do you have the guarantee that no other thread has updated its value in between the read and the write.
The simple solution to this: change counter to an AtomicInteger, and use getAndIncrement or incrementAndGet to increment it.
Secondly, public static class Runnable extends Thread { is extremely dubious.
Don't hide the names of commonly-known Java classes (this is hiding java.lang.Runnable)
Don't extend Thread directly, especially when all you need is a java.lang.Runnable to add execute with an ExecutorService.
A more suitable class declaration would be:
public static class MyRunnable implements Runnable {
(or whatever you want to call it)
Or you can just declare an anonymous class:
executor.execute(new Runnable() { /* body */ });
Or you can just declare a lambda:
executor.execute(() -> { /* body */ });
Thirdly, count doesn't really seem to be serving an obvious purpose here. The logic of the runnable seems to be:
If "flag" is false:
Set "flag" to true
Increment a variable
Set "flag" to false
Otherwise:
Wait 3 seconds
Try again
count is playing the role of "flag" here. It's effectively just an AtomicBoolean.
But you don't need a separate count variable at all, if you make the counter an AtomicInteger:
while (true) {
int current = counter.get();
if (counter.compareAndSet(current, current + 1)) {
// Nothing else is trying to update "current" at the same time:
// we updated it. Stop.
break;
}
// Something else is trying to update at the same time.
// Sleep for 3 seconds.
Thread.sleep(3000);
}
I'm learning multithreaded counter and I'm wondering why no matter how many times I ran the code it produces the right result.
public class MainClass {
public static void main(String[] args) {
Counter counter = new Counter();
for (int i = 0; i < 3; i++) {
CounterThread thread = new CounterThread(counter);
thread.start();
}
}
}
public class CounterThread extends Thread {
private Counter counter;
public CounterThread(Counter counter) {
this.counter = counter;
}
public void run() {
for (int i = 0; i < 10; i++) {
this.counter.add();
}
this.counter.print();
}
}
public class Counter {
private int count = 0;
public void add() {
this.count = this.count + 1;
}
public void print() {
System.out.println(this.count);
}
}
And this is the result
10
20
30
Not sure if this is just a fluke or is this expected? I thought the result is going to be
10
10
10
Try increasing the loop count from 10 to 10000 and you'll likely see some differences in the output.
The most logical explanation is that with only 10 additions, a thread is too fast to finish before the next thread gets started and adds on top of the previous result.
I'm learning multithreaded counter and I'm wondering why no matter how many times I ran the code it produces the right result.
<ttdr> Check out #manouti's answer. </ttdr>
Even though you are sharing the same Counter object, which is unsynchronized, there are a couple of things that are causing your 3 threads to run (or look like they are running) serially with data synchronization. I had to work hard on my 8 proc Intel Linux box to get it to show any interleaving.
When threads start and when they finish, there are memory barriers that are crossed. According to the Java Memory Model, the guarantee is that the thread that does the thread.join() will see the results of the thread published to it but I suspect a central memory flush happens when the thread finishes. This means that if the threads run serially (and with such a small loop it's hard for them not to) they will act as if there is no concurrency because they will see each other's changes to the Counter.
Putting a Thread.sleep(100); at the front of the thread run() method causes it to not run serially. It also hopefully causes the threads to cache the Counter and not see the results published by other threads that have already finished. Still needed help though.
Starting the threads in a loop after they all have been instantiated helps concurrency.
Another thing that causes synchronization is:
System.out.println(this.count);
System.out is a Printstream which is a synchronized class. Every time a thread calls println(...) it is publishing its results to central memory. If you instead recorded the value and then displayed it later, it might show better interleaving.
I really wonder if some Java compiler inlining of the Counter class at some point is causing part of the artificial synchronization. For example, I'm really surprised that a Thread.sleep(1000) at the front and end of the thread.run() method doesn't show 10,10,10.
It should be noted that on a non-intel architecture, with different memory and/or thread models, this might be easier to reproduce.
Oh, as commentary and apropos of nothing, typically it is recommended to implement Runnable instead of extending Thread.
So the following is my tweaks to your test program.
public class CounterThread extends Thread {
private Counter counter;
int result;
...
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt(); // good pattern
return;
}
for (int i = 0; i < 10; i++) {
counter.add();
}
result = counter.count;
// no print here
}
}
Then your main could do something like:
Counter counter = new Counter();
List<CounterThread> counterThreads = new ArrayList<>();
for (int i = 0; i < 3; i++) {
counterThread.add(new CounterThread(counter));
}
// start in a loop after constructing them all which improves the overlap chances
for (CounterThread counterThread : counterThreads) {
counterThread.start();
}
// wait for them to finish
for (CounterThread counterThread : counterThreads) {
counterThread.join();
}
// print the results
for (CounterThread counterThread : counterThreads) {
System.out.println(counterThread.result);
}
Even with this, I never see 10,10,10 output on my box and I often see 10,20,30. Closest I get is 12,12,12.
Shows you how hard it is to properly test a threaded program. Believe me, if this code was in production and you were expecting the "free" synchronization is when it would fail you. ;-)
I'm a little confused about the difference between threading and multi-threading in Java as far as syntax. I need to write a program to print even numbers 0 to 30 and then odds using threading and another program to do the same thing using multi-threading. I wrote a program that runs and does what it's supposed to but I don't know whether it's threading or multi-threading, or how to go about doing the one it isn't. Here is my program-
public class OddEven extends Thread {
public static void main(String args[]){
Runnable r1 = new Runnable1();
Thread t1 = new Thread(r1);
Runnable r2 = new Runnable2();
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
class Runnable1 implements Runnable{
public void run(){
for(int i=0; i<=30; i+=2) {
System.out.println(i);
}
}
}
class Runnable2 implements Runnable{
public void run(){
for(int i=1; i<=30; i+=2){
System.out.println(i);
}
}
}
Would this program be considered just a single thread?
public class OddEven {
public static void main(String args[]){
for(int i=0; i<=30; i+=2) {
System.out.println(i);
}
for(int i=1; i<=30; i+=2){
System.out.println(i);
}
}
}
Multithreading enables you to do multiple works simultaneously.
For example, if you make a game in which a boy moves forward & goes on firing as well. If you use single threading system, then either a boy could move forward or can fire on his enemy at a time. He cant do the both the works simultaneously.
In your case, when you call t1.start();, then a new thread gets started which will execute your Runnable1's method. Then you called t2.start();, immediately, it will also another thread gets started & your Runnable2's method will gets executed.
Both the method will get executed simultaneously. If you don't use multi threading, then only after finishing the first loop, the next loop will get start.
Multi-threading mainly use in the programs where main thread may process for a long time & you want to use other functions of the program.
Hope this helps!!!!
public class MyResource {
private int count = 0;
void increment() {
count++;
}
void insert() { // incrementing shared resource count
for (int i = 0; i < 100000000; i++) {
increment();
}
}
void insert1() { //incrementing shared resource count
for (int i = 0; i < 100000000; i++) {
increment();
}
}
void startThread() {
Thread t1 = new Thread(new Runnable() { //thread incrementing count using insert()
#Override
public void run() {
insert();
}
});
Thread t2 = new Thread(new Runnable() { //thread incrementing count using insert1()
#Override
public void run() {
insert1();
}
});
t1.start();
t2.start();
try {
t1.join(); //t1 and t2 race to increment count by telling current thread to wait
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void entry() {
long start = System.currentTimeMillis();
startThread(); //commenting insert(); insert1() gives output as time taken = 452(approx) 110318544 (obvious)
// insert(); insert1(); //commenting startThread() gives output as time taken = 452(approx) 200000000
long end = System.currentTimeMillis();
long time = end - start;
System.out.println("time taken = " + time);
System.out.println(count);
}
}
Program entry point is from entry() method.
1.Only using insert(); insert1(); (Normal method calling ) and commenting startThread()(which executes thread) gives me result as shown in code.
2.Now commenting insert(); insert1(); and using startThread()(which executes thread) gives me result as shown in code.
3.Now I synchronize increment() gives me output as time taken = 35738 200000000
As Above synchronizing avoids access of shared resource but on other hand it takes lot of time to process.
So what's use of this synchronizing if it decrease the performance ?
Sometimes you just want two or more things to go on at the same time. Imagine the server of a chat application or a program that updates the GUI while a long task is running to let the user know that processing is going on
You are not suppose to use synchronization to increase performance, you are suppose to use it in order to protect shared resources.
Is this a real code example? Because if you want to use threads here in order to split the work synchronize
increment()
is not the best approach...
EDIT
as described here, you can change the design of this specific code to divide the work between the 2 threads more efficiently.
i altered their example to fit your needs, but all the methods described there are good.
import java.util.*;
import java.util.concurrent.*;
import static java.util.Arrays.asList;
public class Sums {
static class Counter implements Callable<Long> {
private final long _limit;
Counter(long limit) {
_limit = limit;
}
#Override
public Long call() {
long counter = 0;
for (long i = 0; i <= _limit; i++) {
counter++
}
return counter;
}
}
public static void main(String[] args) throws Exception {
int counter = 0;
ExecutorService executor = Executors.newFixedThreadPool(2);
List <Future<Long>> results = executor.invokeAll(asList(
new Counter(500000), new Counter(500000));
));
executor.shutdown();
for (Future<Long> result : results) {
counter += result.get();
}
}
}
and if you must use synchronisation, AtomicLong will do a better job.
Performance is not the only factor. Correctness can also be very important. Here is another question that has some low level details about the keyword synchronized.
If you are looking for performance, consider using the java.util.concurrent.atomic.AtomicLong class. It has been optimized for fast, atomic access.
EDIT:
Synchonized is overkill in this use case. Synchronized would be much more useful for FileIO or NetworkIO where the calls are much longer and correctness is much more important. Here is the source code for AtomicLong. Volatile was chosen because it is much more performant for short calls that change shared memory.
Adding a synchronized keyword adds in extra java bytecode that does a lot of checking for the right state to get the lock safely. Volatile will put the data in main memory, which takes longer to access, but the CPU enforces atomic access instead of the jvm generating extra code under the hood.
The below code increments a static variable within a Thread and checks to see if its value is incremented by one. This is what Assert.assertEquals(currentAVal+1, accessCounter); checks.
The test consistently passes for 10'000 runs. But why is no race condition causing the test to fail ?
I would expect two or more threads to increment accessCounter at line accessCounter = accessCounter + 1; before the assert takes place but this does not seem to be occurring ?
public class RunnableTest {
private static int accessCounter = 0;
private class Post implements Runnable {
public void run() {
int currentAVal = accessCounter;
accessCounter = accessCounter + 1;
Assert.assertEquals(currentAVal+1, accessCounter);
System.out.println("Access counter : "+accessCounter);
}
}
#Test
public void runTest(){
Runnable r = new Post();
ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
for(int executorCount = 0; executorCount < 10000; ++executorCount) {
executor.execute(r);
}
}
}
Update : from Gray's answer I've updated the code and I am now receiving a race condition (test failure) when I remove the println statement :
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import junit.framework.Assert;
public class RunnableTest {
private static int accessCounter = 0;
private static List<String> li = new ArrayList<String>();
private class Post implements Runnable {
public synchronized void run() {
int currentAVal = accessCounter;
accessCounter = accessCounter + 1;
li.add(String.valueOf(currentAVal+1+","+accessCounter));
}
}
#Test
public void runTest(){
Runnable r = new Post();
ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
for(int executorCount = 0; executorCount < 10000; ++executorCount) {
executor.execute(r);
}
//Wait for threads to finish
// we shut it down once we've submitted all jobs to it
executor.shutdown();
// now we wait for all of those jobs to finish
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(String s : li){
Assert.assertEquals(s.split(",")[0], s.split(",")[1]);
}
}
}
Adding synchronized to the run method causes the test to pass
The test consistently passes for 10'000 runs. But why is no race condition causing the test to fail ?
The definition of a race condition is that you might get timing problems -- it is not guaranteed. If you ran this on another architecture you might get wildly different results.
However, I don't think that asserts in other threads are seen by junit. For example, if I change you test the following. I do see times that the value differs but the fail is not seen by the test method -- the test still passes.
if (currentAVal+1 != accessCounter) {
System.out.println("Access counter not equal: "+accessCounter);
Assert.fail();
}
One reason why you may be seeing proper values in accessCounter is that System.out.println(...) is a synchronized method which is (as a byproduct) synchronizing the value of accessCounter.
Also, you are not shutting down your executor nor are you waiting for the executor service to actually complete. You should do something like:
// we shut it down once we've submitted all jobs to it
executor.shutdown();
// now we wait for all of those jobs to finish
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
But this doesn't solve the other thread issue. To actually see the results of the threads you could do something like:
List<Future<?>> futures = new ArrayList<Future<?>>();
for (int executorCount = 0; executorCount < 10000; ++executorCount) {
futures.add(executor.submit(r));
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
for (Future<?> future : futures) {
// this will throw an exception if an assert happened
future.get();
}
Firstly as other answers have pointed out that Race is not guaranteed to occur. Remove the sysout statement as that can cause the code to synchronize.
The answer is in the question itself. It's a race condition :
You can't guarantee that it will ever occur no matter HOW many times threads you try to throw at it or times you try to run it. That's why it's a race condition. It's non-deterministic
Assuming uniform probability distribution for this isn't even remotely correct unless you can show why. You aren't flipping a coin here. The code could run for months before the race is exposed, I've seen this very thing happen many times. That's why race conditions are hard to solve and important to prevent.
Secondly you aren't seeding any amount of random noise into the scenario. If you say had each thread's run function sleep a random amount of time first so that they actually were likely to coincide with one another this would be more intersting... but you're threads a so short they are likely finished and never even running in parallel compared to the time it takes to spawn dispatch the jobs.