Reputation: 21
I am trying to write a simple code to print numbers in sequence. Scenario is like
1
2
3
4
5
.. and so on
here is the code I have written
public class CounterThread implements Runnable {
int counterNumber;
public CounterThread(int counterNumber) {
this.counterNumber = counterNumber;
}
@Override
public void run() {
System.out.println(this.counterNumber);
}
public static void main(String[] args) throws InterruptedException {
int number = Integer.parseInt(args[0]);
Thread[] listOfThreads = new Thread[number];
for(int i = 1; i <= number; i++){
CounterThread counterThread = new CounterThread(i);
Thread thread = new Thread(counterThread);
thread.start();
listOfThreads[i-1] = thread;
}
for(Thread thread : listOfThreads){
thread.join();
}
}
}
I realize that this is a very bad coding practice for thread programming, but i am still at a novice level trying to understand how threads behave when synchronized and when not. The output is jumbled which is to be expected but not what is required. i am not sure where i am going wrong, any help is much appreciated.
Upvotes: 2
Views: 988
Reputation: 3027
you can just call the join()
after the start()
because the start of method in first loop cause it to execute and before reaching to the next loop it already did its work, so you need to call it in first loop after start to make sure its ending before starting the next one:
the join() method which allows one thread to wait until another thread completes its execution. If t is a Thread object whose thread is currently executing, then t.join() will make sure that t is terminated before the next instruction is executed by the program.
public class CounterThread implements Runnable {
int counterNumber;
public CounterThread(int counterNumber) {
this.counterNumber = counterNumber;
}
@Override
public void run() {
System.out.println(this.counterNumber);
}
public static void main(String[] args) throws InterruptedException {
int number = Integer.parseInt(args[0]);;
for (int i = 1; i <= number; i++) {
CounterThread counterThread = new CounterThread(i);
Thread thread = new Thread(counterThread);
thread.start();
thread.join();
}
}
}
Upvotes: 1
Reputation: 3226
You can optimize your code by writing this, it will simply make the main thread wait for the current thread
to complete its execution.
for (int i = 1; i <= number; i++) {
CounterThread counterThread = new CounterThread(i);
Thread thread = new Thread(counterThread);
thread.start();
thread.join();
}
However, it is a really strange piece of code. In such cases, where you are not allowed to use synchronized
in multithreaded environment, the best you can go with is using volatile
keyword or atomic variables. Both approaches are designed to make all the writes and reads to the variable atomic.
volatile int number = 1;
...
@Override
public void run() {
System.out.println(number++);
}
...
for (int i = 1; i <= number; i++) {
CounterThread counterThread = new CounterThread();
Thread thread = new Thread(counterThread);
thread.start();
}
But you should note, that volatile
does not give 100% guarantee that you will avoid race condition. Especially in this case, since number++
will not be an atomic operation. It will be actually number = number + 1
- one read and one write.
But with Atomic
, incrementing will be an atomic operation and you can write something like
AtomicInteger number = new AtomicInteger(0);
...
@Override
public void run() {
System.out.println(number.incrementAndGet());
}
Upvotes: 3