How to make threads in Java run concurrently - java

I'm trying out this code and I'm a bit confused/surprised at the output I'm getting. I'm still new to Java but I'm aware that threads should normally run concurrently. It seems my "printB" thread here waits for the "printA" thread before it starts executing. I've run the program several times (hoping to get a mixture of both threads' outcome i.e. something like: a, a, b, a, b, a...) but still I get the same output (i.e. "A" getting printed first, before "B"). Why is this happening and how can I alter the code to start behaving normally?
Any inputs/suggestions would be much appreciated. Thanks.
Also, I'm trying out the same code using the extends Thread method and it doesn't work.
class PrintChars implements Runnable{
private char charToPrint;
private int times;
public PrintChars(char c, int t){
charToPrint = c;
times = t;
}
public void run(){
for (int i=0; i<times; i++)
System.out.println(charToPrint);
}
public static void main(String[] args){
PrintChars charA = new PrintChars('a', 7);
PrintChars charB = new PrintChars('b', 5);
Thread printA = new Thread(charA);
Thread printB = new Thread(charB);
printA.start();
printB.start();
}
}
Extends Thread method below:
class PrintChars extends Thread {
private Char charToPrint;
private int times;
public PrintChars(char c, int t){
charToPrint = c;
times = t;
}
public void run (){
for(int i =0; i<times; i++)
System.out.println(charToPrint);
}
PrintChars printA = new PrintChars('a', 7);
PrintChars printB = new PrintChars('a', 5);
printA.start();
printB.start();
}

In multithreading, usually you can't make any assumption about the output.
Perhaps the time used to create the thread is very long, hence the previous thread has time to complete entirely, since its execution is very short.
Try with 7000 and 5000 instead of 7 and 5.

Each thread takes time to start and can run to completion very quickly. I suggest you add Thread.sleep(500); after each line printed.
try {
for(int i =0; i<times; i++) {
System.out.println(charToPrint);
Thread.sleep(500);
}
} catch(InterruptedException ie) {
}

Try running it a few more times. When I tried it with 700/500 I noticed some interweaving.

Thread scheduling is not deterministic. It's perfectly fine for the OS to schedule one thread, and only schedule the second after the first has completed.
If you think about it from the OS' point of view, it makes sense.. If somebody asked you to do two tasks, it may be more efficient to do one and then the other.
When the task takes too long to execute, as an OS you'll probably want to task switch and do something on the other task as otherwise the other task won't progress at all, and the app. that issued the task will feel discriminated.
You can see this by making your task run longer, e.g. by adding Thread.sleep statements or calculating PI or something (or just loop for more than 7, like 70000).

I think the execution times for your threads are too short to notice an effect. You can try higher values for times. I would try something >10000. Another option is to increase the execution time by making the method slower:
public void run(){
for (int i = 0; i < times; i++) {
System.out.println(charToPrint);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

Your code is behaving normally only, if your expectation is to have mixture of a and b's printed, then you should sufficiently print chars not just couple of times, or use Thread.sleep() or do a busy wait running a for loop doing nothing for a million times.

Related

Issues with Threads. Trying to test a timer that utilizes threads and seem to get stuck in a loop

My TEST creates an instance of SimpleTimer with 1000 as a milliseconds measure to delay the thread by 1 second.
#Test
public void testSimpleTimerAsThread() throws InterruptedException
{
SimpleTimer st = new SimpleTimer(1000);
st.start();
Thread.sleep(250);
for(int x = 0; x<5; x++)
{
assertEquals(x, st.getRound());
Thread.sleep(1000);
}
}
My METHOD
timeChanged() just updates the round number and calls for all observers to update their time.
public void start()
{
for(int r = 0; r<5; r++)
{
try
{
timeChanged();
Thread.sleep(1000);
}
catch (InterruptedException e)
{
}
}
}
SimpleTimer extends Thread and implements an interface that doesn't really mess with this code.
When I run this i get the java assertion error saying it expected 0 but was 5 so x never incremented and the round increased by 5.
Your SimpleTimer works in the same thread as the rest, so when you call st.start() what happens is it goes straight there and executes everything, then the rest of your test is executed. You need to put all of your SimpleTimer logic in run method instead of start method and remove start method completely, Thread class already has it implemented in the right way (but keep call to st.start(), it's ok, that's how you start a new Thread). But even then it's not gonna work as expected, but this will actually be concurrency problem, not a mistake. I mean there is a slight possibility that it's gonna work (only sometimes, not always), because of the delays, but relying on delays it's not really a good idea.

Java concurrency counter not properly clean up

This is a java concurrency question. 10 jobs need to be done, each of them will have 32 worker threads. Worker thread will increase a counter . Once the counter is 32, it means this job is done and then clean up counter map. From the console output, I expect that 10 "done" will be output, pool size is 0 and counterThread size is 0.
The issues are :
most of time, "pool size: 0 and countThreadMap size:3" will be
printed out. even those all threads are gone, but 3 jobs are not
finished yet.
some time, I can see nullpointerexception in line 27. I have used ConcurrentHashMap and AtomicLong, why still have concurrency
exception.
Thanks
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicLong;
public class Test {
final ConcurrentHashMap<Long, AtomicLong[]> countThreadMap = new ConcurrentHashMap<Long, AtomicLong[]>();
final ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
final ThreadPoolExecutor tPoolExecutor = ((ThreadPoolExecutor) cachedThreadPool);
public void doJob(final Long batchIterationTime) {
for (int i = 0; i < 32; i++) {
Thread workerThread = new Thread(new Runnable() {
#Override
public void run() {
if (countThreadMap.get(batchIterationTime) == null) {
AtomicLong[] atomicThreadCountArr = new AtomicLong[2];
atomicThreadCountArr[0] = new AtomicLong(1);
atomicThreadCountArr[1] = new AtomicLong(System.currentTimeMillis()); //start up time
countThreadMap.put(batchIterationTime, atomicThreadCountArr);
} else {
AtomicLong[] atomicThreadCountArr = countThreadMap.get(batchIterationTime);
atomicThreadCountArr[0].getAndAdd(1);
countThreadMap.put(batchIterationTime, atomicThreadCountArr);
}
if (countThreadMap.get(batchIterationTime)[0].get() == 32) {
System.out.println("done");
countThreadMap.remove(batchIterationTime);
}
}
});
tPoolExecutor.execute(workerThread);
}
}
public void report(){
while(tPoolExecutor.getActiveCount() != 0){
//
}
System.out.println("pool size: "+ tPoolExecutor.getActiveCount() + " and countThreadMap size:"+countThreadMap.size());
}
public static void main(String[] args) throws Exception {
Test test = new Test();
for (int i = 0; i < 10; i++) {
Long batchIterationTime = System.currentTimeMillis();
test.doJob(batchIterationTime);
}
test.report();
System.out.println("All Jobs are done");
}
}
Let’s dig through all the mistakes of thread related programming, one man can make:
Thread workerThread = new Thread(new Runnable() {
…
tPoolExecutor.execute(workerThread);
You create a Thread but don’t start it but submit it to an executor. It’s a historical mistake of the Java API to let Thread implement Runnable for no good reason. Now, every developer should be aware, that there is no reason to treat a Thread as a Runnable. If you don’t want to start a thread manually, don’t create a Thread. Just create the Runnable and pass it to execute or submit.
I want to emphasize the latter as it returns a Future which gives you for free what you are attempting to implement: the information when a task has been finished. It’s even easier when using invokeAll which will submit a bunch of Callables and return when all are done. Since you didn’t tell us anything about your actual task, it’s not clear whether you can let your tasks simply implement Callable (may return null) instead of Runnable.
If you can’t use Callables or don’t want to wait immediately on submission, you have to remember the returned Futures and query them at a later time:
static final ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
public static List<Future<?>> doJob(final Long batchIterationTime) {
final Random r=new Random();
List<Future<?>> list=new ArrayList<>(32);
for (int i = 0; i < 32; i++) {
Runnable job=new Runnable() {
public void run() {
// pretend to do something
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(r.nextInt(10)));
}
};
list.add(cachedThreadPool.submit(job));
}
return list;
}
public static void main(String[] args) throws Exception {
Test test = new Test();
Map<Long,List<Future<?>>> map=new HashMap<>();
for (int i = 0; i < 10; i++) {
Long batchIterationTime = System.currentTimeMillis();
while(map.containsKey(batchIterationTime))
batchIterationTime++;
map.put(batchIterationTime,doJob(batchIterationTime));
}
// print some statistics, if you really need
int overAllDone=0, overallPending=0;
for(Map.Entry<Long,List<Future<?>>> e: map.entrySet()) {
int done=0, pending=0;
for(Future<?> f: e.getValue()) {
if(f.isDone()) done++;
else pending++;
}
System.out.println(e.getKey()+"\t"+done+" done, "+pending+" pending");
overAllDone+=done;
overallPending+=pending;
}
System.out.println("Total\t"+overAllDone+" done, "+overallPending+" pending");
// wait for the completion of all jobs
for(List<Future<?>> l: map.values())
for(Future<?> f: l)
f.get();
System.out.println("All Jobs are done");
}
But note that if you don’t need the ExecutorService for subsequent tasks, it’s much easier to wait for all jobs to complete:
cachedThreadPool.shutdown();
cachedThreadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
System.out.println("All Jobs are done");
But regardless of how unnecessary the manual tracking of the job status is, let’s delve into your attempt, so you may avoid the mistakes in the future:
if (countThreadMap.get(batchIterationTime) == null) {
The ConcurrentMap is thread safe, but this does not turn your concurrent code into sequential one (that would render multi-threading useless). The above line might be processed by up to all 32 threads at the same time, all finding that the key does not exist yet so possibly more than one thread will then be going to put the initial value into the map.
AtomicLong[] atomicThreadCountArr = new AtomicLong[2];
atomicThreadCountArr[0] = new AtomicLong(1);
atomicThreadCountArr[1] = new AtomicLong(System.currentTimeMillis());
countThreadMap.put(batchIterationTime, atomicThreadCountArr);
That’s why this is called the “check-then-act” anti-pattern. If more than one thread is going to process that code, they all will put their new value, being confident that this was the right thing as they have checked the initial condition before acting but for all but one thread the condition has changed when acting and they are overwriting the value of a previous put operation.
} else {
AtomicLong[] atomicThreadCountArr = countThreadMap.get(batchIterationTime);
atomicThreadCountArr[0].getAndAdd(1);
countThreadMap.put(batchIterationTime, atomicThreadCountArr);
Since you are modifying the AtomicInteger which is already stored into the map, the put operation is useless, it will put the very array that it retrieved before. If there wasn’t the mistake that there can be multiple initial values as described above, the put operation had no effect.
}
if (countThreadMap.get(batchIterationTime)[0].get() == 32) {
Again, the use of a ConcurrentMap doesn’t turn the multi-threaded code into sequential code. While it is clear that the only last thread will update the atomic integer to 32 (when the initial race condition doesn’t materialize), it is not guaranteed that all other threads have already passed this if statement. Therefore more than one, up to all threads can still be at this point of execution and see the value of 32. Or…
System.out.println("done");
countThreadMap.remove(batchIterationTime);
One of the threads which have seen the 32 value might execute this remove operation. At this point, there might be still threads not having executed the above if statement, now not seeing the value 32 but producing a NullPointerException as the array supposed to contain the AtomicInteger is not in the map anymore. This is what happens, occasionally…
After creating your 10 jobs, your main thread is still running - it doesn't wait for your jobs to complete before it calls report on the test. You try to overcome this with the while loop, but tPoolExecutor.getActiveCount() is potentially coming out as 0 before the workerThread is executed, and then the countThreadMap.size() is happening after the threads were added to your HashMap.
There are a number of ways to fix this - but I will let another answer-er do that because I have to leave at the moment.

incrementing a static variable thru' 100 different threads without synchronisation, yet getting the final result as 100

I'm incrementing a static variable thru' 100 different threads without synchronisation, yet getting the final result as 100. I've run this code several times and have got same result. Does my code then not require synchronisation? I'm using BlueJ IDE to run the code
public class Main {
private final static int MAX_THREADS = 100;
public static void main(String[] args) {
Thread[] threads = new Thread[MAX_THREADS];
for(int i=0; i<MAX_THREADS; i++) {
threads[i] = new Thread(new Job(), "Thread-" + i);
threads[i].start();
try{
Thread.sleep((int)(Math.random() * 1000));
}catch(InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0; i<MAX_THREADS; i++) {
try {
threads[i].join();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Final Value: %d\n", Job.getSuccessCount());
}
}
public class Job implements Runnable {
private static int successCount;
public static int getSuccessCount() {return successCount;}
#Override
public void run() {
System.out.printf("%s: Incrementing successCount %d\n", Thread.currentThread().getName(), successCount);
try{
Thread.sleep((int)(Math.random() * 10000));
}catch(InterruptedException e) {
e.printStackTrace();
}
successCount++;
System.out.printf("%s: Incrementing Complete %d\n", Thread.currentThread().getName(), successCount);
}
}
Basically in you code, due to the sleep statements (both in the Thread and by the launcher), you are effectively kicking off the threads allowing for plenty of non busy time to update. That is why it is working. If you code was really multi-threaded, the you would face synchronization issues.
Adding to Wombat's Answer. The final result will always be 100 because you do a Unary Operation after The Sleep in Job class. Basically the read-modify-write commands can run sequentially per Job if the Java Scheduler didn't change the status of the Thread while performing the following.
successCount++
But if you change the Job source code to read-sleep-modify-write then you will definitely see stale value as following.
public class Job implements Runnable {
private static int successCount;
public static int getSuccessCount() {return successCount;}
#Override
public void run() {
System.out.printf("%s: Incrementing successCount %d\n", Thread.currentThread().getName(), successCount);
int sc = successCount; // Read
try{
Thread.sleep((int)(Math.random() * 10000)); // Sleep
}catch(InterruptedException e) {
e.printStackTrace();
}
successCount = sc++; // Modify-Write
System.out.printf("%s: Incrementing Complete %d\n", Thread.currentThread().getName(), successCount);
}
}
With this 2 Threads can read and then sleep and then wake up and write the same value to successCount overwriting the original value.
Your code currently doesn't need synchronization, as no two treads access the same variable at the same time. In other words, only 1 thread in your application is incrementing the variable.
In this case, it is due to the fact that incrementing the variable takes less than Math.random() *1000. Why is it so? Let's observe the threads:
Main Thread:
Launches and starts a thread
Executes both Math.random() and Thread.sleep()
Loops again
While the main thread is doing step 2, the new thread is:
Incrementing variable
Going to sleep
In this case, once the new thread goes to sleep, it just is killed right after, therefore, for our purpose we can regard it as if the thread terminates right after step 1, as it stops affecting the variable (it has no influence on the variable after step 1).
In order for a synchronization problem to occur, two new threads need to access the variable at once. For this to happen, main thread must launch a new thread before the first new thread finishes incrementing. For that to happen, main thread must be faster in: executing Math.random(), Thread.sleep(), and creating a new thread, all before the other thread finishes incrementing. This is obviously not the case, and thus no 2 threads will increment at once, and no synchronization error will occur.
If you do the sums you'll see that you have an average of ten threads running at the same time, all sleeping for an average of five seconds and then doing an increment. So on average the increments won't be closer together than half a second, and the fact their starting is also spaced out by an average of half a second makes that a full second on average. There is essentially no concurrency here at all.

why is this thread safe?

Because it always prints out '3'. No synchronization needed? I am testing this simple thing because I am having a trouble in a real multiple thread problem, which isn't good to illustrate the problem, because it's large. This is a simplified version to showcase the situation.
class Test {
public static int count = 0;
class CountThread extends Thread {
public void run()
{
count++;
}
}
public void add(){
CountThread a = new CountThread();
CountThread b = new CountThread();
CountThread c = new CountThread();
a.start();
b.start();
c.start();
try {
a.join();
b.join();
c.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
Test test = new Test();
System.out.println("START = " + Test.count);
test.add();
System.out.println("END: Account balance = " + Test.count);
}
Because it always prints out '3'. No synchronization needed?
It is not thread safe and you are just getting lucky. If you run this 1000 times, or on different architectures, you will see different output -- i.e. not 3.
I would suggest using AtomicInteger instead of a static field ++ which is not synchronized.
public static AtomicInteger count = new AtomicInteger();
...
public void run() {
count.incrementAndGet();
}
...
Seems to me like count++ is fast enough to finish until you invoke 'run' for the other class. So basically it runs sequential.
But, if this was a real life example, and two different threads were usingCountThread parallelly, then yes, you would have synchronization problem.
To verify that, you can try to print some test output before count++ and after, then you'll see if b.start() is invoking count++ before a.start() finished. Same for c.start().
Consider using AtomicInteger instead, which is way better than synchronizing when possible -
incrementAndGet
public final int incrementAndGet()
Atomically increments by one the current value.
This code is not thread-safe:
public static int count = 0;
class CountThread extends Thread {
public void run()
{
count++;
}
}
You can run this code a million times on one system and it might pass every time. This does not mean is it is thread-safe.
Consider a system where the value in count is copied to multiple processor caches. They all might be updated independently before something forces one of the caches to be copied back to main RAM. Consider that ++ is not an atomic operation. The order of reading and writing of count may cause data to be lost.
The correct way to implement this code (using Java 5 and above):
public static java.util.concurrent.atomic.AtomicInteger count =
new java.util.concurrent.atomic.AtomicInteger();
class CountThread extends Thread {
public void run()
{
count.incrementAndGet();
}
}
It's not thread safe just because the output is right. Creating a thread causes a lot of overhead on the OS side of things, and after that it's just to be expected that that single line of code will be done within a single timeslice. It's not thread safe by any means, just not enough potential conflicts to actually trigger one.
It is not thread safe.
It just happened to be way to short to have measurable chance to show the issue. Consider counting to much higher number (1000000?) in run to increase chance of 2 operations on multiple threads to overlap.
Also make sure your machine is not single core CPU...
To make the class threadsafe either make count volatile to force memory fences between threads, or use AtomicInteger, or rewrite like this (my preference):
class CountThread extends Thread {
private static final Object lock = new Object();
public void run()
{
synchronized(lock) {
count++;
}
}
}

Two Loops at almost the same time

i don't what this process is called, but i've seen that it's possible.
what is this process called?
basically, i have a method that has a loop, and in every iteration has a delay second.
function myLoop(float delay)
{
for(int x=0; x<100; x++)
{
Print("Loop number: " + x);
TimeDelay(delay);
}
}
i'd like to run the second instance without waiting until the first instance is finished.
function main()
{
myLoop(2);
myLoop(2);
}
so once the first myLoop started, i'd like the second myLoop to start immediately, they would be both running at the same time, my question is, what do you call this process?
is this process possible?(in java for example).
Thank you very much! :)
This typically requires some form of multithreading.
You would do something like:
function main
start thread, calling myLoop(2)
start thread, calling myLoop(2)
' Potentially wait for threads to complete
end function
For details on how this works in Java, see the Concurrency Tutorial.
Java implementation of your program will be similar to this.
class MyThread implements Runnable{
Thread t;
int delay;
MyThread (int delay) {
t = new Thread(this,"My thread");
this.delay = delay;
t.start();
}
public void run() {
for(int x=0; x<100; x++)
{
Print("Loop number: " + x);
TimeDelay(delay);
}
}
}
class Demo {
public static void main (String args[]){
Thread t1 = new MyThread(2);
Thread t2 = new MyThread(2);
t1.join();
t2.join();
}
}
The answer for your questions.
What is this called?
A: Threading - running multiple tasks at a same time. (We call it as forking in PHP/Linux applications.)
Is this possible in Java?
A: Offcourse this is possible. To be frank this is more easier to implement in Java. Please follow the above answers.
This is called an asynchronous computation. You can solve this cleanly with Futures. (You don't really need to do full-blown multithreading)
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html

Categories

Resources