Java Concurrency- Runnable vs Thread - java

I have decided to face this monster called concurrency and broaden my threading knowledge, so before I read through Joshua Bloch's book, I decided to code something random to help me understand the problem I might face before reading the book, hopefully I can then come to my code and make corrections but then I landed into this pit and I am hoping someone can explain.
I have the following:
public class Arithmetic implements Runnable {
int number;
public Arithmetic(int x){
this.number = number + x;
}
#Override
public void run() {
Thread.currentThread().setName("thread-"+number +" > " + "number = "+getNumber());
System.out.println(Thread.currentThread().getName());
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = getNumber() + number;
}
}
Then a main class:
public class Main {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
for (int x=0; x<=5; x++){
Thread thread = new Thread(new Arithmetic(x));
thread.start();
}
}
}
With this I get the following as output:
run:
main
thread-0 > number = 0
thread-1 > number = 1
thread-2 > number = 2
thread-3 > number = 3
thread-5 > number = 5
thread-4 > number = 4
Notice: The 5 comes before 4
But then I change my main class to:
public class Main {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
for (int x=0; x<=5; x++){
Runnable runnable = new Arithmetic(x);
runnable.run();
}
}
}
I get the output below:
run:
main
thread-0 > number = 0
thread-1 > number = 1
thread-2 > number = 2
thread-3 > number = 3
thread-4 > number = 4
thread-5 > number = 5
Notice: Correct sequence
I was hoping both main(s) will produce erratic result(Like Thread implementation), then I would then use some thread safety measures like synchronised access etc. but why does the Runnable call act as if Arithmetic is thread safe?
IMO, the difference between extending Thread class and implementing Runnable is for decoupling purposes. Apologies if this is a duplicate question, I can't seem to find an answer.
Thanks in advance.

Runnables do not start new threads it is simply and interface, so this means your second piece of code runs synchronously.
Threads are new threads so you they can run in parallel, which is why the output comes out of order - the 4th thread executes slower than the 5th.

The thing is when you do
Thread t = new Thread(new Arithemetic())
t.start();
The thread t is started and it executed Arithmetic.
In your case you are calling runnable.run();, which means the current thread shall call code inside your run(). It is similar to calling any other method.
Ultimately, your current thread in itself is executing the run method 5 times

Your Runnables are all executing in the main thread (and in that code there is only the one "main" thread).
Your threads all execute separately, and java give no guarantee that once started threads will execute in any particular order.

Because Runnable itself doesn't run on a seperate thread. It is just an interface used for passing a method implementation around. One example of such is passing it to a Thread constructor (as you have done in your first example). Thus in your second example, nothing is being executed concurrently; it's just executing the run() methods one after the other.

Related

Why do these synchronized methods keep giving me different outputs?

I need this threads that have access to the same data to be execute simultaneously without messing around with each other, so instead using Thread.join() I've been trying with synchronized methods. Problem is that I see no change at all, it keep giving me the same result that I had before using them. I don't even know what exactly I'm doing wrong, synchronized
methods suppose to prevent other synchronized methods to execute until they are done, right? Hope you can give me some clue about what is goin' on.
public class ThreadSync{
public static void main(String[] args) throws InterruptedException {
//if execute properly
//output can't be other than 0
while(true) {
ChangeValue counter = new ChangeValue();
Threads t = new Threads(counter,"up");
Threads t2 = new Threads(counter,"down");
Threads t3 = new Threads(counter,"print");
t.start();
t2.start();
t3.start();
}
}
}
class Threads extends Thread{
Threads(ChangeValue obj, String act){
counter = obj;
action = act;
}
#Override
public void run() {
switch(action) {
case ("up"): counter.up(); break;
case ("down"): counter.down(); break;
case ("print"): counter.print(); break;
}
}
ChangeValue counter;
String action;
}
class ChangeValue{
public synchronized void up() { value++; }
public synchronized void down() { value--; }
public synchronized void print() { System.out.println(value); }
public int value = 0;
}
The synchronization just ensures that the methods are not executed at the same time. However, it does not guarantee any execution order.
You need to ensure that print() is not executed before the other threads have terminated. This could be achieved by joining the threads. To do so, execute
t.join();
t2.join();
either before starting the print thread or before executing its logic.
Note that the synchronization is still sensible because it ensures that the increment and decrement operations are executed atomically. That is, that reading, incrementing, and writing count when executing count++ are executed at once
(see also: Why is i++ not atomic?). Thereby it prevents the following execution sequence:
[Thread "up"]: load count with value 0
[Thread "down"]: load count with value 0
[Thread "up"]: increment count to 1
[Thread "down"]: decrement count to -1
[Thread "up"]: store count with value 1
[Thread "down"]: store count with value -1
(This is a "lost update" in database terms.)
synchronized prevens your thread from accessing the field simultaneously, but of course it provides no guarantee regarding the order in which the threads execute.
For example, if, by pure chance, the "Up" thread executes first, the "Print" thread second and the "Down" thread last, the output will be 1, even though the counter value is 0 after all threads are finished.

Thread execution after .start() method

I am wondering what happens in the following scenario:
Two threads are created:
Thread t1 = new Thread();
Thread t2 = new Thread();
Assume these just print out a string, the threads then call the .start() method:
t1.start();
t2.start():
My question is why do these threads print in a seemingly random order each time? I know threads execute concurrently but would t1 not always finish before t2 due to the sequential execution of the main process?
Calling start() on a Thread doesn't necessarily result in the thread running immediately after. It is possible for other things to happen in between your calling start() and the first line of your thread's run() method actually being run. And even once your run() is actually running, it's also possible that other things happen before, during, or after your run() method finishes.
In your question, you said: "assume these just print out a string" – here's an implementation of run() which does that:
public void run() {
System.out.println("my name is: " + getName());
}
So it's possible that t1 starts to run first, but before it actually calls System.out.println, t2 is allowed to execute and runs to completion, then t1 is resumed.
If this kind of behavior won't work for your use case, you'll need to add some kind of concurrency protection to coordinate how and when your threads run.
UPDATE:
To illustrate the unpredictable sequence of thread execution, run this code a few times and observe the output:
public class Example {
public static void main(String[] args) {
for (int k = 0; k < 10; k++) {
new TestThread(k).start();
}
}
}
class TestThread extends Thread {
private final int k;
TestThread(int k) {
this.k = k;
}
#Override
public void run() {
System.out.print(k + " ");
}
}
Here is the output from one of my local runs:
7 0 1 5 4 6 3 2 8 9
Thread.start() doesn't guarantee execution. It will just make the Thread state runnable and hand over to the Thread Scheduler. It is the Thread Scheduler which decides which thread to run when.
If you need code to execute in a defined order on multiple threads, you need to add synchronization code between those threads.
Otherwise, the system is free to schedule execution in any order it sees fit.

Java Puzzler: busy wait threads stop working

This is some sort of a Java Puzzler, that I stumbled across and can't really explain. Maybe somebody can?
The following program hangs after a short time. Sometimes after 2 outputs, sometimes after 80, but almost always before terminating correctly. You might have to run it a few times, if it doesn't happen the first time.
public class Main {
public static void main(String[] args) {
final WorkerThread[] threads = new WorkerThread[]{ new WorkerThread("Ping!"), new WorkerThread("Pong!") };
threads[0].start();
threads[1].start();
Runnable work = new Runnable() {
private int counter = 0;
public void run() {
System.out.println(counter + " : " + Thread.currentThread().getName());
threads[counter++ % 2].setWork(this);
if (counter == 100) {
System.exit(1);
}
}
};
work.run();
}
}
class WorkerThread extends Thread {
private Runnable workToDo;
public WorkerThread(String name) {
super(name);
}
#Override
public void run() {
while (true){
if (workToDo != null) {
workToDo.run();
workToDo = null;
}
}
}
public void setWork(Runnable newWork) {
this.workToDo = newWork;
}
}
Now, it's clear that busy waiting loops are not a great idea in general. But this not about improving, it's about understanding what is happening.
Since everything works as expected when WorkerThread.setWork() is synchronized or when the WorkerThread.workToDo field is set to volatile I suspect a memory issue.
But why exactly is it happening? Debugging doesn't help, once you start stepping through, everything behaves as expected.
An explanation would be appreciated.
The first problem is that you are setting the Runnable workToDo from the main thread and then reading it in the 2 forked threads without synchronization. Any time you modify a field in multiple threads, it should be marked as volatile or someone synchronized.
private volatile Runnable workToDo;
Also, because multiple threads are doing counter++ this also needs to be synchronized. I recommend an AtomicInteger for that.
private AtomicInteger counter = new AtomicInteger(0);
...
threads[counter.incrementAndGet() % 2].setWork(this);
But I think the real problem may be one of race conditions. It is possible for both threads to set the workToDo to be the Runnable and then have them both return and set it back to be null so they will just spin forever. I'm not sure how to fix that.
1. threads[0] has it's `workToDo` set to the runnable. It calls `run()`.
2. at the same time threads[1] also calls `run()`.
3. threads[0] sets the `workToDo` on itself and threads[1] to be the runnable.
4. at the same time threads[1] does the same thing.
5. threads[0] returns from the `run()` method and sets `workToDo` to be `null`.
6. threads[1] returns from the `run()` method and sets `workToDo` to be `null`.
7. They spin forever...
And, as you mention, the spin loop is crazy but I assume this is a demonstration thread program.
The problem occurs right between these lines:
workToDo.run();
workToDo = null;
Suppose the following sequence of events occurs:
- Original Runnable runs. "Ping!".setWork() called
- Ping! thread realizes workToDo != null, calls run(), the stops between those two lines
- "Pong!".setWork() called
- Pong! thread realizes workToDo != null, calls run()
- "Ping!".setWork() called
- Ping! thread resumes, sets workToDo = null, ignorantly discarding the new value
- Both threads now have workToDo = null, and the counter is frozen at 2,...,80
Program hangs
my 2 cents....
import java.util.concurrent.atomic.AtomicReference;
class WorkerThread extends Thread {
private AtomicReference<Runnable> work;
public WorkerThread(String name) {
super(name);
work = new AtomicReference<Runnable>();
}
#Override
public void run() {
while (true){
Runnable workToDo = work.getAndSet(null);
if ( workToDo != null ) {
workToDo.run();
}
}
}
public void setWork(Runnable newWork) {
this.work.set(newWork);
}
}

Synchronized method not threadsafe

Can someone please let me know why is the below code not threadsafe ? The output I get is either 0 or 45 or 90. The shared resource counter has a synchronized method, so I am expecting 90 as the output all the times. Am I missing something here ? Please advise.
Kindly, also let me know how to make this code threadsafe.
class Counter{
long count = 0;
public synchronized void add(long value){
this.count += value;
}
}
class CounterThread extends Thread{
protected Counter counter = null;
public CounterThread(Counter counter){
this.counter = counter;
}
public void run() {
for(int i=0; i<10; i++){
counter.add(i);
}
}
}
public class Example {
public static void main(String[] args){
Counter counter = new Counter();
Thread threadA = new CounterThread(counter);
Thread threadB = new CounterThread(counter);
threadA.start();
threadB.start();
System.out.println(counter.count);
}
}
wait for threads to finish. Add
threadA.join();
threadB.join();
before printing the result.
Essentially you are reading the values before the two threads have completed their execution.
You can use a join to wait for the threads to finish.
Also try using AtomicLong 's addAndGet method instead of the synchronized add method.
You do not wait with the println until the threads have stopped. So you print out the value of the counter while the for-loops are still in process. It does not have to do anything with thread-safety.
Counter access is threadsafe, but System.out.println(counter.count); can happen before other threads do their work.
Your code is thread safe but a better way is get rid of synchronized method and use AtomicLong
And Use getAndAdd(long) method
public final long getAndAdd(long delta)
>Atomically add the given value to current value.
You have 3 threads running there. The one assigned to variable threadA, the one assigned to threadB and the main thread.
The main thread runs as long as the main method runs. The other 2 are started and run concurrently with the main thread. However, the main thread is not blocked waiting for the other 2 to finish, so it prints the result when it gets a chance to execute.

How to Synchronize Threads

In this multithreading program, when I run it, I always get the output in some random order. But I was wondering if there is any way I can make this program to work in synchronized mode. Like when I runt it then for the first thread it should print out everything, then for second thread it should print out something, then for third thread it should print out everything etc etc. So sample output should be like this for each thread-
Task 1 Started
original: Hello World
Difference:- 0
Task 1 Ended
Task 2 Started
original: Hello World
Difference:- 0
Task 2 Ended
............
............
Task 15 Started
original: Hello World
Difference:- 0
Task 15 Ended
This is my below program. Any suggestions will be appreciated.
class ThreadTask implements Runnable {
private int id;
public ThreadTask(int id) {
this.id = id;
}
public synchronized void run() {
System.out.println("Task " + id + " Started ");
String originalString = "Hello World";
System.out.println("original: " + originalString);
System.out.println("Task " + id + " Ended ");
}
}
public class TestPool {
public static void main(String[] args) throws InterruptedException {
int size = 5; //Integer.parseInt(args[0]);
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(size);
// queue some tasks
for(int i = 1; i <= 3 * size; i++) {
service.submit(new ThreadTask(i));
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
You commented on Jakub's answer as follows:
Can you give me example basis on my code as I just started learning about threading. It will be of great help to me.
What Jakub is saying is that forcing threads to run in a fixed sequence defeats the purpose of using threads in the first place. Think about this.
If you really do want / need your example to run the tasks in order, you may as well do this:
for (int i = 1; i <= 3 * size; i++) {
new ThreadTask(i).run();
}
i.e. just run the runnables in the current thread.
Or you could set the maximum pool size to 1, which forces the service to run the tasks in order. (Of course, this defeats the point of using threads. You won't get any parallelism this way.)
A more sensible approach would be to have each thread return its results in a Future, and then have the main thread fetch the value from each future (in the required order) and print it. Basically, you want to allow the threads to run in any order (and in parallel, if you have multiple cores), but then impose the ordering when you access the results.
The essence of thread is that they can run simultaneously, if you want them to run in order, simply do not use Thread.
There's another kind of requirement, that maybe you want several jobs to work together (simultaneously), but in a given order. In this case, I highly suggest you to implement a queuing system. That is, build a queue like
Queue <C> q
And a thread
class T implements Runnable {
public void run() {
while (!q.empty()) {
// Do something
}
}
}
You can use Runnable through ExecutorService, like the code that you've used.
You can also add some elements into the queue in "Do something" section of previous code, then you can control the order of jobs by yourself.
You can save the the reference to the previous thread and hook up the next thread to the previous one using join(). That will ensure the threads will be run in a series (next one not starting unless the previous one finished). But the point of doing that is eluding me.
public class TestPool
{
static class ThreadTask extends Thread
{
private int id;
private Thread previous;
public ThreadTask(int id, Thread previous){
this.id = id;
this.previous = previous;
}
public void run(){
if(previous != null){
try{
previous.join();
}
catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println("Task " + id + " Started ");
String originalString = "Hello World";
System.out.println("original: " + originalString);
System.out.println("Task " + id + " Ended ");
}
}
public static void main(String[] args) throws InterruptedException{
int size = 5; // Integer.parseInt(args[0]);
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(size);
Thread previous = null;
// queue some tasks
for(int i = 1; i <= 3 * size; i++){
Thread thread = new ThreadTask(i, previous);
previous = thread;
thread.start();
//service.submit(thread);
}
// wait for termination
//service.shutdown();
//service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
Not tested, sry. I don't also know what the ExecutorService is doing, it might break this. Note that I need to be a Thread, being Runnable is not enough. Also, run() needs not be synchronised, as it will be called only once per execution. And you should not start the threads with run(), but with start().
EDIT: I just tried to run it, and the ExecutorService is fu**ing things up. If you just start the thread (like the my code does), then it's working.

Categories

Resources