package workouts;
public class synchro {
private int count = 0;
public void counting() {
Thread T1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
Thread T2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
T1.start();
T2.start();
try {
T1.join();
T2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("counting =" + count);
}
public static void main(String[] args) {
synchro sync = new synchro();
sync.counting();
}
}
but when introduced a synchronised method and call it inside run method like below.. the output is 20000 for how many times if u run it..can someone explain the difference between the above and below code
public class synchro {
private int count = 0;
public synchronized void dosinglethread(){
count++;
}
public void counting() {
Thread T1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
dosinglethread();
}
}
});
Thread T2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
dosinglethread();
}
}
});
T1.start();
T2.start();
try {
T1.join();
T2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("counting =" + count);
}
public static void main(String[] args) {
synchro sync = new synchro();
sync.counting();
}
}
When you say count++, three things happen:
The current value of count is retrieved by the VM
The VM increments the value by 1
The new value is put back into count
It's entirely possible that T1 and T2 both get the value of count, then increment it separately, and then but back the result, like so:
Timeslot T1 T2
1 count = 3 ----
2 ---- count = 3
3 3 + 1 = 4 ----
4 ---- 3 + 1 = 4
5 store 4 in count ----
6 ---- store 4 in count
So now, count++ has been called twice, but the value has only increased by one. To prevent this, you have to make the increment atomic. Atomic means that either the entire sequence of operations is executed, or none of it is. Simply put, if two statements are synchronized on the same Object, they will not interleave.
In your second piece of code, dosinglethread() is declared synchronized. This is the equivalent of:
public void dosinglethread() {
synchronized (this) {
count++;
}
}
This means that when one of the threads starts executing it, they acquire a lock on your synchro instance. When the second thread also tries to execute the method, it will see that another thread already owns the lock on this, so it has to wait. When the first thread completes the method, it will release the lock and the other thread can then take it.
So why didn't volatile work? volatile variables will not cause threads to wait until they are available. Instead, when count is volatile and you call count++, the following happens: (Code adapted from Javamex's Tutorial)
int temp;
synchronized (count) {
temp = count;
}
temp = temp + 1;
synchronized (count) {
count = temp;
}
Note that this code is for illustration only: synchronized can not be used on primitives.
It's clear, then, that the threads might still be paused at temp = temp + 1, giving the same problems as when you don't do any synchronization.
For more information, check the tutorial I mentioned.
Related
I am writing a program that uses multithreading to add a array from 1 to 1000, there are 5 threads in total, the result should be different every time, but I get the correct answer every time. How can I make data inconsistency issue? I need to make it result race condition.
public class SyncDemo1 {
public static void main(String[] args) {
new SyncDemo1().startThread(); //need something else beside the correct answer 500500
}
private void startThread() {
int[] num = new int[1000];
ExecutorService executor = Executors.newFixedThreadPool(5);
MyThread thread1 = new MyThread(num, 1, 200);
MyThread thread2 = new MyThread(num, 201, 400);
MyThread thread3 = new MyThread(num, 401, 600);
MyThread thread4 = new MyThread(num, 601, 800);
MyThread thread5 = new MyThread(num, 801, 1000);
executor.execute(thread1);
executor.execute(thread2);
executor.execute(thread3);
executor.execute(thread4);
executor.execute(thread5);
executor.shutdown();
while (!executor.isTerminated()) {
}
int temp = thread1.getSum() + thread2.getSum() + thread3.getSum() + thread4.getSum()+ thread5.getSum();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
int totalSum = temp;
System.out.println(totalSum);
}
private static void pause() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private static class MyThread implements Runnable {
private int[] num;
private int from , to , sum;
public MyThread(int[] num, int from, int to) {
this.num = num;
this.from = from;
this.to = to;
sum = 0;
}
public void run() {
for (int i = from; i <= to; i++) {
sum += i;
}
pause();
}
public int getSum() {
return this.sum;
}
}
}
If you need to experiment with race conditions, you can experiment using this demo class
class RaceConditionDemo implements Runnable {
private int counter = 0;
public void increment () {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
counter++;
}
public void decrement () {
counter--;
}
public int getValue () {
return counter;
}
#Override
public void run () {
this.increment();
System.out.println("Value for Thread After increment "
+ Thread.currentThread().getName() + " " + this.getValue());
this.decrement();
System.out.println("Value for Thread at last "
+ Thread.currentThread().getName() + " " + this.getValue());
}
public static void main (String args[]) {
RaceConditionDemo counter = new RaceConditionDemo();
Thread t1 = new Thread(counter, "Thread-1");
Thread t2 = new Thread(counter, "Thread-2");
Thread t3 = new Thread(counter, "Thread-3");
Thread t4 = new Thread(counter, "Thread-4");
Thread t5 = new Thread(counter, "Thread-5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
Here, the Runnable class contains a primitive int as a shared resource. As you may know, primitives are not thread-safe and pre-increment nor post-increment are atomic operations. Run enough times, and you will notice the values printed out are not predictable.
I feel weird posting this as an answer because your question seeks code that is implemented incorrectly. This is a first for me.
The output (of one of the runs)
Value for Thread After increment Thread-3 5
Value for Thread After increment Thread-5 5
Value for Thread After increment Thread-1 5
Value for Thread After increment Thread-2 5
Value for Thread at last Thread-2 1
Value for Thread After increment Thread-4 5
Value for Thread at last Thread-1 2
Value for Thread at last Thread-5 3
Value for Thread at last Thread-3 4
Value for Thread at last Thread-4 0
Notice how, sometimes, one thread executes it's run() method while another thread is still in the middle of the execution. So you may see "Value for Thread After increment" printed out consecutively before either one got a chance to execute the decrement and print out "Value for Thread at last". This causes an instability in the value being printed out. In fact, it is possible that the value of the counter variable changes just before one thread finishes the increment or decrement.
I have a snippet of code that creates 3 threads and expect them to print sequentially using synchronized block on the integer object. But apparently I am getting deadlock sometimes. See below:
public class SequentialExecution implements Runnable {
private Integer i = 1;
public void run() {
String tmp = Thread.currentThread().getName();
if (tmp.equals("first")) {
synchronized(i) {
first();
i = 2;
}
} else if (tmp.equals("second")) {
while (i != 2);
synchronized(i) {
second();
i = 3;
}
} else {
while (i != 3);
synchronized(i) {
third();
}
}
}
public void first() {
System.out.println("first " + i);
}
public void second() {
System.out.println("second " + i);
}
public void third() {
System.out.println("third " + i);
}
public static void main(String[] args) {
//create 3 threads and call first(), second() and third() sequentially
SequentialExecution se = new SequentialExecution();
Thread t1 = new Thread(se, "first");
Thread t2 = new Thread(se, "second");
Thread t3 = new Thread(se, "third");
t3.start();
t2.start();
t1.start();
}
}
The result I am expecting(and sometimes getting) is:
first 1
second 2
third 3
One sample result I am getting with deadlock(and eclipse hangs) is:
first 1
second 2
Anyone know why this is not working? I know I can use locks but I just don't know why using synchronized block is not working.
Declare i to be volatile: private volatile Integer i = 1;. This warns the compiler that it must not apply certain optimizations to i. It must be read from memory each time it is referenced in case another thread has changed it.
I also agree with the recommendation in user3582926's answer to synchronize on this rather than i, because the object referenced by i changes as the program runs. It is neither necessary nor sufficient to make the program work, but it does make it a better, clearer program.
I have tested each change by changing the main method to:
public static void main(String[] args) throws InterruptedException {
// create 3 threads and call first(), second() and third() sequentially
for (int i = 0; i < 1000; i++) {
SequentialExecution se = new SequentialExecution();
Thread t1 = new Thread(se, "first");
Thread t2 = new Thread(se, "second");
Thread t3 = new Thread(se, "third");
t3.start();
t2.start();
t1.start();
t1.join();
t2.join();
t3.join();
}
}
There is no deadlock. There is a memory order issue.
The while loops in the second and third threads are outside any synchronized block. There is nothing telling the compiler and JVM that those threads cannot keep i, or the object to which it points, in a register or cache during the loop. The effect is that, depending on timing, one of those threads may get stuck looping looking at a value that is not going to change.
One way to solve the problem is to mark i volatile. That warns the compiler that it is being used for inter-thread communication, and each thread needs to watch for changes in memory contents whenever i changes.
In order to solve it entirely using synchronization, you need to check the value of the Integer referenced by i inside a block that is synchronized on a single, specific object. i is no good for that, because it changes due to boxing/unboxing conversion. It might as well be a simple int.
The synchronized blocks cannot wrap the while loops, because that really would lead to deadlock. Instead, the synchronized block has to be inside the loop. If the updates to i are synchronized on the same object, that will force the updates to be visible to the tests inside the while loops.
These considerations lead to the following synchronization-based version. I am using a main method that does 1000 runs, and will itself hang if any thread in any of those runs hangs.
public class SequentialExecution implements Runnable {
private int i = 1;
public void run() {
String tmp = Thread.currentThread().getName();
if (tmp.equals("first")) {
synchronized (this) {
first();
i = 2;
}
} else if (tmp.equals("second")) {
while (true) {
synchronized (this) {
if (i == 2) {
break;
}
}
}
synchronized (this) {
second();
i = 3;
}
} else {
while (true) {
synchronized (this) {
if (i == 3) {
break;
}
}
}
synchronized (this) {
third();
}
}
}
public void first() {
System.out.println("first " + i);
}
public void second() {
System.out.println("second " + i);
}
public void third() {
System.out.println("third " + i);
}
public static void main(String[] args) throws InterruptedException {
// create 3 threads and call first(), second() and third() sequentially
for (int i = 0; i < 1000; i++) {
SequentialExecution se = new SequentialExecution();
Thread t1 = new Thread(se, "first");
Thread t2 = new Thread(se, "second");
Thread t3 = new Thread(se, "third");
t3.start();
t2.start();
t1.start();
t1.join();
t2.join();
t3.join();
}
}
}
I believe you want to be using synchronized(this) instead of synchronized(i).
I have tried this code. But after printing 0 , it doesn't print anything.
It is blocking due to some lock I think.
public class EvenOdd implements Runnable {
private Object o = new Object();
private volatile int i = 0;
public void run() {
try {
System.out.println();
if ( Thread.currentThread().getName().equals( "Even")) {
printEven();
} else {
printOdd();
}
} catch ( Exception ee) {
ee.printStackTrace();
}
}
private void printEven() throws InterruptedException {
while ( true) {
synchronized ( o) {
while ( this.i % 2 == 0) {
o.wait();
}
System.out.println( Thread.currentThread().getName() + i);
i++;
o.notify();
}
}
}
private void printOdd() throws InterruptedException {
while ( true) {
synchronized ( o) {
while ( this.i % 2 != 0) {
o.wait();
}
System.out.println( Thread.currentThread().getName() + i);
i++;
o.notify();
}
}
}
}
My TestClass:
EvenOdd x = new EvenOdd();
new Thread(x,"Even").start();
new Thread(x,"Odd").start();
Where am I wrong?
Thank.
P.S : I know this type of question has been asked many times , but I want to try by my own.
My guesses is you are;
using one Runnable but both of then think they are even i.e. they both see the first value of 0
printEven has to wait for an odd number ad printOdd has to wait for an even number
EDIT: After running the code the OP fixed the code, it prints
0
1
as expected. It may sometimes print 0 and 0 randomly as the first check for odd/even is not synchronized.
It's a simple deadlock:
Thread 1 waits for someone to notify on the lock. Thread 2 waits for someone to notify on the same lock.
Since no one ever gets to o.notify();, nothing happens.
And i is 0 when both threads start, so both first call printEven(). Now when that has happened, both threads will then call printOdd() in the next round.
The basic concept is when one thread is running, the other has to wait. Once the thread prints the value, it has to wait until the other thread prints. This is achieved by using wait/notify mechanism.
When Odd thread completes printing the value, it notifies the waiting thread(Even thread) and the Even thread becomes ready to run but will wait for the lock to be released by the Odd thread. Now the odd thread calls wait on the locker object so that it releases the lock and goes to wait state. At this point, the only thread waiting for locker object's lock is Even thread and it runs. This process continues alternatively.
public class Test {
public static void main(String[] args) {
Object locker = new Object();
Thread t1 = new Thread(new OddWorker(locker));
Thread t2 = new Thread(new EvenWorker(locker));
t1.start();
t2.start();
}
}
class OddWorker implements Runnable {
private Object locker;
private int number = 1, count = 1;
OddWorker(Object locker) {
this.locker = locker;
}
#Override
public void run() {
synchronized (locker){
do {
try {
System.out.println(Thread.currentThread().getName() + ": " + number);
number += 2;
locker.notify();
locker.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} while(++count < 11);
locker.notify();
}
}
}
class EvenWorker implements Runnable {
private Object locker;
private int number = 2, count = 1;
EvenWorker(Object locker) {
this.locker = locker;
}
#Override
public void run() {
synchronized (locker){
do {
try {
System.out.println(Thread.currentThread().getName() + ": " + number);
number += 2;
locker.notify();
locker.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} while(++count < 11);
}
}
}
I have an array : int[] arr = {5,4,3,1,2};
I want to do like this::
5 should be read by thread one
4 should be read by thread two
3 should be read by thread one
1 should be read by thread two
2 should be read by thread one
I have tried my best this simple program:
package com.techighost.create.deadlock;
public class ArrayReading implements Runnable {
volatile int index = 0;
int[] arr;
public ArrayReading(int[] arr) {
this.arr = arr;
}
#Override
public void run() {
synchronized (arr) {
for (;index<=(arr.length-1);) {
if (index % 2 == 0 && Thread.currentThread().getName().equals("Thread-One")) {
System.out.println(arr[index] + " " + Thread.currentThread().getName());
index++;
arr.notify();
} else if (index % 2 != 0 && Thread.currentThread().getName().equals("Thread-Two")) {
System.out.println(arr[index] + " " + Thread.currentThread().getName());
index++;
arr.notify();
}else{
System.out.println("In else " + Thread.currentThread().getName());
try {
arr.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
int[] arr = { 5, 4, 3, 1, 2 };
ArrayReading arrayReading = new ArrayReading(arr);
Thread t = new Thread(arrayReading);
t.setName("Thread-One");
Thread t1 = new Thread(arrayReading);
t1.setName("Thread-Two");
t.start();
t1.start();
t.join();
t1.join();
}
}
I think that this thread name check should not be there? Any body please suggest what can be done to remove this check
You can use condition as mentioned by #zzk.Program
for this can be as
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class PrintSequentially {
private final int[] items;
private final ReentrantLock lock;
private final Condition notEven;
private final Condition notOdd;
private int currentCount = 0;
public PrintSequentially(int[] items) {
this.items = items;
this.lock = new ReentrantLock();
this.notEven = lock.newCondition();
this.notOdd = lock.newCondition();
}
public void printSeq() throws InterruptedException {
try {
lock.lockInterruptibly();
while (currentCount < items.length) {
if (currentCount % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":"
+ items[currentCount++]);
if (currentCount < items.length)
notEven.await();
notOdd.signal();
} else {
System.out.println(Thread.currentThread().getName() + ":"
+ items[currentCount++]);
notEven.signal();
if (currentCount < items.length)
notOdd.await();
}
}
} finally {
lock.unlock();
}
}
}
Driver program for this is
public static void main(String[] args) {
int arr[] ={1,2,3,4,5};
final PrintSequentially p = new PrintSequentially(arr);
Runnable r1 = new Runnable() {
#Override
public void run() {
try {
p.printSeq();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable r2 = new Runnable() {
#Override
public void run() {
try {
p.printSeq();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread th1 = new Thread(r1);
th1.setName("thread 1");
th1.start();
Thread th2 = new Thread(r2);
th2.setName("thread 2");
th2.start();
}
Here you can add as many thread you want. It will print sequentially.
You could use conditions. Thread 1 should wait for condition index % 2 == 0 and Thread 2 should wait for condition index % 2 == 1.
Look at this link for how to use condition
Use another parameter field in your runnable to tell it to read even or odd indices, create two instances of your runnable, one for even, one for odd. Set up an ExecutorService with at least two threads, execute the runnables. It may be possibile they finish too fast to be given different threads. Did not test this.
I understand that this probably is some sort of getting-your-feet-wet thread application but there are a number of problems with it that makes it less than optimal.
The whole point of using threads is asynchronous operation. Wanting your threads to process every other entry in an array sounds like you are dividing up the work but this may run slower than single threaded because of the synchronization to accomplish the every other. The nature of threads also means that "2" may be printed before "1". That's a good thing because you aren't slowing down a thread to get them to be in order.
Your code has some race conditions here. For example, a thread could process the last element of the list and go to wait but the other thread could have already finished the list and won't be there to notify it. I bet your application often hangs at the end.
You should consider using an executor service and submitting a job for each entry. This is the best way to do most threaded task:
// create a thread pool with 2 workers
ExecutorService threadPool = Executors.newFixedThreadPool(2);
for (int entry : arr) {
threadPool.submit(new `(entry));
}
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
// to wait for the jobs to finish you do
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
...
Then your ArrayReading takes the entry not the whole array and can work on them independently.
Lastly, as others have already mentioned, you could pass a boolean even flag to have each thread process even (if true) or odd (if false) items.
Thread t1 = new Thread(new ArrayReading(arr, true));
Thread t2 = new Thread(new ArrayReading(arr, false));
You can use inter thread communication using wait and notify like this :
class ReadNum
{
int arr[];
private volatile int counter = 0;
public ReadNum()
{
counter = 0 ;
}
public ReadNum(int size)
{
arr = new int[size];
for (int i = 0; i < size ; i++)
{
arr[i] = i;
}
}
public void setArray(int[] arr)
{
counter = 0;
this.arr = arr;
}
public synchronized void readOdd()
{
while (counter < arr.length)
{
if (counter % 2 != 0)
{
System.out.println(Thread.currentThread().getName()+":->"+arr[counter]);
counter++;
}
notify();
try{
wait();
}catch(Exception ex){ex.printStackTrace();}
}
notify();//So that other EvenThread does'nt hang if OddThread completes earlier
}
public synchronized void readEven()
{
while (counter < arr.length)
{
if (counter % 2 == 0)
{
System.out.println(Thread.currentThread().getName()+":->"+arr[counter]);
counter++;
}
notify();
try{
wait();
}catch(Exception ex){ex.printStackTrace();}
}
notify();//So that other OddThread does'nt hang if EvenThread completes earlier
}
}
public class SequenceRead
{
public static void main(String st[])
{
final ReadNum rn = new ReadNum();
int arr[]= {1,2,34,78,99,45,4545,987,343,45};
rn.setArray(arr);
Thread th1 = new Thread(new Runnable()
{
#Override
public void run()
{
rn.readEven();
}
},"EvenReadThread");
Thread th2 = new Thread( new Runnable()
{
#Override
public void run()
{
rn.readOdd();
}
},"OddReadThread");
th2.start();th1.start();
}
}
UPDATE
Here is the explanation that you asked for about Race Condition.
Race Condition : "It is a situation where multiple threads can access same resource (typically object's instance variables) and can
produce corrupted data if one thread "races in" or "sneaks in" too
quickly before an operation that should be atomic has completed. Hence the output of program is unpredictable because it is dependent on the sequence or timing of starting, execution and completion of the various threads accessing the same resource ."
For example consider the code given below:
class Race
{
private int counter;
public void printCounter()
{
while(counter < 100)
{
try
{
Thread.sleep(10);//Added to show Race Effect.
}
catch (Exception ex){}
counter = counter + 1;
}
System.out.println(Thread.currentThread().getName() +" : "+counter);//If we don't consider Race condition then the Output should be 100 for all threads.
}
}
public class MainClasss
{
public static void main(String st[])
{
final Race race = new Race();
Thread[] th = new Thread[2];
//Creating 2 threads to call printCounter of object race
for (int i = 0 ; i < th.length ; i++)
{
th[i] = new Thread( new Runnable()
{
public void run()
{
race.printCounter();
}
}, "Thread"+i);
}
//Starting all Threads
for (Thread thr : th )
{
thr.start();
}
}
}
And here is the output that that I am getting , It might vary on your system.
Thread1 : 100
Thread0 : 101
All threads are not printing 100 as expected!!! Why ? Because Program has no control on when an executing Thread will be preempted by another thread.It all depends upon JVM Thread Scheduler.One of the possible explanations for above output is as follows:
At counter = 99 , Thread1 sneaked inside the while loop and slept for 10 ms .
JVM Scheduler now preempted Thread1 by Thread0 .
Thread1 goes inside "while" loop because it finds counter < 100
At Thread.sleep Thread0 is preempted by Thread1.
Thread1 increases the counter by 1.
Thread1 prints the counter value as 100 and finishes.
Thread0 continues execution and increases the counter by 1 and makes counter = 101
Thread0 prints the counter value as 101 and finishes.
This is the live exhibition of Race Condition.
To Avoid this Race condition you should make the ReadNum method as synchronized , So that when a Thread enters that method , it takes the monitor and become owner of the synchronized method . And that thread is preempted only after it completes the all operation Atomically . I hope it gave you a good overview of Race Condition now.
here is the code you are looking for ....
public class ThreadConcurrent {
int []array=new int[]{0,1,2,3,4,5,6,7,8,9};
volatile int i=0;
public void checkSum() {
synchronized (this) {
for(;i<array.length;){
System.out.println("thread name "+Thread.currentThread().getName()+ " : "+array[i]);
i++;
notify();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
final ThreadConcurrent er=new ThreadConcurrent();
Thread t1=new Thread(new Runnable() {
#Override
public void run() {
er.checkSum();
}
}, "T1");
Thread t21=new Thread(new Runnable() {
#Override
public void run() {
er.checkSum();
}
}, "T2");
t1.start();
t21.start();
}
}
Basically what it does is that it prints the following numbers multiple of 2 and 3 in sequence like this
2 3 4 6 6 9 8 12 10 = this is the output
(2*1=2) (3*1=3) (2*2=4) (3*2=6) (2*3=6) (3*3=9) (2*4=8) (3*4=12) (2*5=10) = just a guide
here's my code so far, I'm having trouble displaying it in sequence. I've tried using wait and notify but it's a mess. So far this one is working.
public class Main {
public static void main(String[] args) throws InterruptedException {
final Thread mulof2 = new Thread(){
public void run() {
for (int i = 1; i <= 10; i++) {
int n = 2;
int result = n * i;
System.out.print(result + " ");
}
}
};
Thread mulof3 = new Thread(){
public void run() {
for (int i = 1; i <= 10; i++) {
int n = 3;
int result = n * i;
System.out.print(result + " ");
}
}
};
mulof2.start();
mulof3.start();
}
}
With Java 7 your first choice should be a Phaser. You'll only need one instance of it, created with new Phaser(1). You'll need just two methods for coordination: arrive and awaitAdvance.
Multiplication Table in java using Threads Concept
public class Multiplication extends Thread {
public void run() {
for (int i = 1; i < 10; i++) {
int n = 2;
int result = n * i;
System.out.print(i+"*"+n+"="+result+"\n");
}
}
public static void main(String[] args) throws InterruptedException {
Multiplication mul=new Multiplication();
mul.start();
}
}
Instead of printing during computation, you can aggregate the results into strings and then print both strings in order. After joining with the threads of course.
wait() and notify() are generally too low level, and too complex to use. Try using a more high-level abstraction like Semaphore.
You could have a pair of Semaphore instances: one which allows printing the next multiple of 2, and another one which allows printing the next multiple of 3. Once the next multiple of 2 has been printed, the thread should give a permit to print the next multiple of 3, and vice-versa.
Of course, the initial numbers of permits of the semaphores must be 1 for the multiple-of-2 semaphore, and 0 for the other one.
A simple modification would help you get the required sequence.
You need to declare a semaphore as other have pointed out private Semaphore semaphore;. Then declare another variable to denote which thread has to execute next such as private int threadToExecute; .
Next step is within your thread execute the code between semaphore.acquire(); and semaphore.release();
thread2:
try{
semaphore.acquire();
if(threadToExecute ==2)
semaphore.release();
//write your multiply by 2 code here
threadToExecute = 3;
semaphore.release();
}catch(Exception e){
//exceptions
}
This will nicely synchronize your output.
Below is the code that will give you desired results.
public class Main {
public static void main(String[] args) throws InterruptedException {
final Object lock1 = new Object();
final Object lock2 = new Object();
final Thread mulof2 = new Thread(){
public void run() {
for (int i = 1; i <= 10; i++) {
synchronized (lock1) {
synchronized (lock2) {
lock2.notify();
int n = 2;
int result = n * i;
printResult(result);
}
try {
lock1.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
Thread mulof3 = new Thread(){
public void run() {
for (int i = 1; i <= 10; i++) {
synchronized (lock2) {
synchronized (lock1) {
lock1.notify();
int n = 3;
int result = n * i;
printResult(result);
}
try {
lock2.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
mulof2.start();
mulof3.start();
}
static void printResult(int result)
{
try {
// Sleep a random length of time from 1-2s
System.out.print(result + " ");
Thread.sleep(new Random().nextInt(1000) + 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}