I have two threads thread1(printing numbers) & thread2(printing alphabets).
My goal is to have the following output via syncronization:
1
a
2
b
3
c
4
d
5
e
class thread1 implements Runnable {
public void run() {
try {
for (int i = 1; i <= 5; i++) {
System.out.println("Is Thread1 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));
synchronized (Testing.class) {
System.out.println("Is Thread1 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));
try {
System.out.println(i);
Testing.class.notifyAll();
System.out.println("Thread1:Going to wait");
Testing.class.wait();
System.out.println("Thread1:Resuming from wait");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Finsihed thread1");
} catch (Exception e) {
System.out.println(e);
}
}
}
class thread2 implements Runnable {
char[] alphabets = { 'a', 'b', 'c', 'd', 'e' };
public void run() {
try {
for (int i = 0; i < 5; i++) {
System.out.println("Is Thread2 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));
synchronized (Testing.class) {
try {
System.out.println("Is Thread2 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));
System.out.println("Thread2:Going to wait");
Testing.class.wait();
System.out.println("Thread2:Resuming from wait");
System.out.println(alphabets[i]);
Testing.class.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
System.out.println(e);
}
}
}
public class Testing {
public static void main(String[] args) {
Testing w= new Testing();
thread1 t1 = new thread1();
thread2 t2 = new thread2();
Thread th1 = new Thread(t1, "");
Thread th2 = new Thread(t2, "");
try {
th1.start();
th2.start();
} catch (Exception e) {
System.out.println(e);
}
}
}
I am getting the output:
Is Thread1 holding lock of
Testing.class?:false
Is Thread1 holding lock of
Testing.class?:true
1
Thread1:Going to wait
Is Thread2 holding lock of
Testing.class?:false
Is Thread2 holding lock of
Testing.class?:true
Thread2:Going to wait
How did thread2 got hold the lock of Testing.class when it was already locked by thread1?. Also, Is there any other elegant way to achieve this sync?. Thanks in advance.
Read a bit more about Java Concurrency.
Calling wait releases the lock.
When you call the wait() method, the thread that you call it in is temporarily giving up the lock. So while thread1 is waiting inside the wait() method, it is not holding the lock, and thread2 can get the lock.
When the wait() method returns, the thread will hold the lock again.
The API documentation of the wait() method in class Object explains this in detail.
The basic problem you have is that you release the synchronized block allowing both threads to go through the loop at the same time. This means either thread can obtain the lock in any order.
AFAIK, The simplest solution is to use a flag.
final int length = 10;
final AtomicBoolean flag = new AtomicBoolean();
new Thread(new Runnable() {
public void run() {
for (int i=1;i<=length;i++) {
while(flag.get());
System.out.print(i+" ");
flag.set(true);
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (char c='a';c<'a'+length;c++) {
while(!flag.get());
System.out.print(c+" ");
flag.set(false);
}
System.out.println();
}
}).start();
The most elegant way to have this task done in sync is to have one thread. Threads are specificly designed to execute two tasks with as little dependence as possible between them.
BTW
If notifyAll() is called before wait() is called, the notify will be lost. wait() will wait forever.
You create a Testing object you discard (remove it).
You trap InterruptedException which you print and continue as if nothing happened (i.e. remove the nested catch)
This is the complete working code
public class MyClass
{
MyClass mClass;
public void doTest()
{
final int [] a = {1,2,3,4,5,6,7,8,9,10};
final char [] c = {'a','b','c','d','e','f','g','h','i','j'};
mClass = this;
Thread t1 = new Thread(new Runnable(){
public void run()
{
for(int i = 0 ; i<a.length ; i++)
{
synchronized(mClass)
{
System.out.print(a[i]+" ");
mClass.notify();
try{mClass.wait();}catch(Exception e){}
}
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable(){
public void run()
{
for(int i = 0 ; i<c.length ; i++)
{synchronized(mClass)
{
System.out.print(c[i]+" ");
mClass.notify();
try{mClass.wait();}catch(Exception e){}
}
}
}
});
t2.start();
}
public static void main(String [] ar)
{
new MyClass().doTest();
}
}
public class MyClass
{
MyClass mClass;
boolean isFirstStartedRunning = true;
public void doTest()
{
final int [] a = {1,2,3,4,5,6,7,8,9,10};
final char [] c = {'a','b','c','d','e','f','g','h','i','j'};
mClass = this;
Thread t1 = new Thread(new Runnable(){
public void run()
{
isFirstStartedRunning = false;
for(int i = 0 ; i<a.length ; i++)
{
synchronized(mClass)
{
System.out.print(a[i]+" ");
mClass.notify();
if(i==a.length-1)return;
try{mClass.wait();}catch(Exception e){}
}
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable(){
public void run()
{
if(isFirstStartedRunning){
try{mClass.wait();}catch(Exception e){}
}
for(int i = 0 ; i<c.length ; i++)
{
synchronized(mClass)
{
System.out.print(c[i]+" ");
mClass.notify();
if(i==a.length-1)return;
try{mClass.wait();}catch(Exception e){}
}
}
}
});
t2.start();
}
public static void main(String [] ar)
{
new MyClass().doTest();
}
}
check the answer now
Related
I want to display this two threads alternatively like that :
Thread 1
Thread 0
Thread 1
Thread 0
...
That's the basic code from where I started, I tried with wait() notify() Methods but I couldn't get the result wanted.
class Task extends Thread {
#Override
public void run() {
try {
for(int i = 0; i<10; i++){
double dure = Math.random()*200 ;
sleep((long) dure);
System.out.println(Thread.currentThread().getName());
}
} catch (Exception e) {
}
}
}
public class App {
public static void main(String[] args) {
Task t1 = new Task() ;
Task t2 = new Task() ;
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
}
}
} ```
I see two solutions:
Busy Wait
Each thread wait before printing. And release when the condition is true. I used AtomicInteger for indexToPrint to make this value sync for every thread.
This solution works with n number of threads.
import java.util.concurrent.atomic.AtomicInteger;
class Task extends Thread {
final static private AtomicInteger indexToPrint = new AtomicInteger(0);
static private int threadNumber = 0;
final private int index;
/**
*
*/
public Task() {
index = threadNumber++;
}
private int nextIndex() {
return (index + 1) % threadNumber;
}
#Override
public void run() {
try {
for(int i = 0; i<10; i++){
double dure = Math.random()*200 ;
sleep((long) dure);
while (indexToPrint.get() != index) {
sleep((long) 10);
}
indexToPrint.set(nextIndex());
System.out.println(Thread.currentThread().getName());
}
} catch (Exception e) {}
}
}
wait and notify
A bit more complex to understand, but no useless CPU use. Let's explain how the synchronized block synchronized (indexToPrint) {...} works.
The block is synchronized monitoring the static object indexToPrint. This object is static (common to every thread), so only one thread can simultaneously enter this block.
When one thread enter the block, if its index is different from indexToPrint then the thread is stopped with wait() making it possible for another thread to enter the block. Else, the thread name is printed, the indexToPrint is updated to next thread index and all thread are waken up with notifyAll(). Finally, it left the block.
All threads waiting are now awake, and the actual thread left the block. So one thread can try again to print.
It's important to understand that when a thread is put to wait and then notify, it runs exactly where it was stopped. Here, a thread can be stopped at two positions: before the synchronized block and at the wait call.
The while is very essential here. All thread are waking up with notifyAll(), so after waking up they should test themselves again.
You can find a good documentation here.
The code is based on the previous one. With same use of indexToPrint.
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
class Task extends Thread {
static private final AtomicInteger indexToPrint = new AtomicInteger(0);
static private int threadNumber = 0;
final private int index;
final private static ArrayList<Task> tasks = new ArrayList<>();
/**
*
*/
public Task() {
index = threadNumber++;
tasks.add(this);
}
private int nextIndex() {
return (index + 1) % threadNumber;
}
#Override
public void run() {
try {
for(int i = 0; i<10; i++){
double dure = Math.random()*200 ;
sleep((long) dure);
synchronized (indexToPrint) {
while (indexToPrint.get() != index) {
indexToPrint.wait();
}
indexToPrint.set(nextIndex());
System.out.println(Thread.currentThread().getName());
indexToPrint.notifyAll();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
The random sleep time can cause the unexpected result also within the main method making the main thread sleep between the start of Thread1 and Thread2 can help you to know who is the first thread that will start the print task , after that you should give the right sleep time inside the task to give the Threads the possibility to prints alternatively .
class Task extends Thread {
#Override
public void run() {
try {
for(int i = 0; i<10; i++){
sleep(2000);
System.out.println(Thread.currentThread().getName());
}
} catch (Exception e) {
}
}
}
public class App {
public static void main(String[] args) {
Task t1 = new Task() ;
Task t2 = new Task() ;
t1.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t2.start();
}
}
I am trying to work around with threads in java. Though I understand that threads output are unpredictable, However was wondering if there is a way to do that.
I have to implement two threads, one prints alphabets(a,b,c...z) and other prints numbers(1,2,3....26). Have to implement it in such a way that the output should be a,1,b,2,c,3,d,4......z,26. Below is my code but it doesn't give the desired output.
public class ThreadsExample {
public static void main(String[] args) {
Runnable r = new Runnable1();
Thread t = new Thread(r);
Runnable r2 = new Runnable2();
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
}
class Runnable2 implements Runnable{
public void run(){
for(char i='a';i<='z';i++) {
System.out.print(i+",");
}
}
}
class Runnable1 implements Runnable{
public void run(){
for(int i=1;i<=26;i++) {
System.out.print(i+",");
}
}
}
What tweak should I make in the code to get the desired output? How does synchronization helps here? Or is it really possible when working with Threads at all?
PS: This is not an assignment or some exercise. Its self learning.
It is possible. You need to synchronize it well.
Approach Pseudocode
query some (synchronized) state
state will tell whether nums or chars are allowed
if state allows char and caller will put chars, do it now and change state and wake up waiting threads
if not, wait
if state allows numbers and caller will put numbers, do it now and change state and wake up waiting threads
if not, wait
Java code
public class ThreadsExample {
public static ThreadsExample output = new ThreadsExample ();
public static void main(String[] args) {
Runnable r = new Runnable1();
Thread t = new Thread(r);
Runnable r2 = new Runnable2();
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
private Object syncher = new Object (); // we use an explicit synch Object, you could use annotation on methods, too. like ABHISHEK did.
// explicit allows to deal with more complex situations, especially you could have more the one locking Object
private int state = 0; // 0 allows chars, 1 allows ints
public void print (char pChar) {
synchronized (syncher) { // prevent the other print to access state
while (true) {
if (state == 0) { // char are allowed
System.out.print(pChar + ","); // print it
state = 1; // now allow ints
syncher.notify(); // wake up all waiting threads
return;
} else { // not allowed for now
try {
syncher.wait(); // wait on wake up
} catch (InterruptedException e) {
}
}
}
}
}
public void print (int pInt) {
synchronized (syncher) {
while (true) {
if (state == 1) {
System.out.print(pInt + ",");
state = 0;
syncher.notify();
return;
} else {
try {
syncher.wait();
} catch (InterruptedException e) {
}
}
}
}
}
}
class Runnable2 implements Runnable{
public void run(){
for(char i='a';i<='z';i++) {
ThreadsExample.output.print(i);
}
}
}
class Runnable1 implements Runnable{
public void run(){
for(int i=1;i<=26;i++) {
ThreadsExample.output.print(i);
}
}
}
Output
a,1,b,2,c,3,d,4,e,5,f,6,g,7,h,8,i,9,j,10,k,11,l,12,m,13,n,14,o,15,p,16,q,17,r,18,s,19,t,20,u,21,v,22,w,23,x,24,y,25,z,26,
The whole idea of threads: it represents a "stream of activity" that executes code independent of other threads.
In your case, you want that these two threads go in "lockstep". Thread A does one step, then Thread B, then A, then B.
In order to get there, the two threads need something "synchronize" on - in other words: A sends a signal to B when it has done its steps - and B has to wait for that signal. Then B does its thing, signals to A, ...
For starters, a simple boolean value would do. One thread sets it to true, the other to false (to indicate when it has made its step). Then the thread waits for the boolean to toggle again.
As you intend to learn things, I would just start experimenting from there. In case you want to take detours, look here for example. This might help as well.
HERE IS THE CODE::
You need to create 2 threads and implement wait and notify methods correctly you can also refer "Create two threads, one display odd & other even numbers" for your answer.
public class ThreadClass {
volatile int i = 1;
volatile Character c = 'a';
volatile boolean state = true;
synchronized public void printAlphabet() {
try {
while (!state) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " +c);
state = false;
c++;
notifyAll();
}
synchronized public void printNumbers() {
try {
while (state) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + i);
state = true;
i++;
notifyAll();
}
public static void main(String[] args) {
ThreadClass threadClass = new ThreadClass();
Thread t1 = new Thread() {
int k = 0;
#Override
public void run() {
while (k < 26) {
threadClass.printAlphabet();
k++;
}
}
};
t1.setName("Thread1");
Thread t2 = new Thread() {
int j = 0;
#Override
public void run() {
while (j < 26) {
threadClass.printNumbers();
j++;
}
}
};
t2.setName("Thread2");
t1.start();
t2.start();
}
}
Your threads are running at the same time. But not the way you want it, as mentioned above. You will see blocks of data from thread 1 and then a block of data from thread 2; and this is because of thread scheduling. Thread 1 is just queuing its output before thread 2.
To test this theory, increase your output to a 1000 records for example as the alphabet and 26 numbers are not as large to see this.
By doing so, you will see these 'blocks' of data. There is a way to do what you mentioned, but it is not advisable as this is not demonstrating how threads actually work but rather you forcing it to work that way.
With less Code:
class MyRunnable implements Runnable {
private static int n = 1;
private static char c = 'a';
public void run() {
for (int i = 1; i <= 26; i++) {
synchronized (this) {
try {
notifyAll();
if (Thread.currentThread().getName().equals("A")) {
System.out.print(c + ",");
c++;
} else {
System.out.print(n + ",");
n++;
}
if (i != 26) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class PrintAlphabetNumberJob {
public static void main(String[] args) throws InterruptedException {
MyRunnable r = new MyRunnable();
Thread tAlphabet = new Thread(r, "A");
Thread tNumber = new Thread(r, "N");
tAlphabet.start();
Thread.sleep(100);
tNumber.start();
}
}
For creating a deadlock in between two threads by accessing print method into Threads. I have used cyclic Barrier so that both of the thread starts at same time. If I am correct my print method is not taking time, for that reason it is getting shared by the two threads and not causing a Deadlock.
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class TWOTHREADDEADLOCLK {
static int b =0;
synchronized static void print()
{
System.out.println(Thread.currentThread().getName() + " " + b);
}
synchronized static int getb()
{
print();
return b;
}
synchronized static void updateb()
{
print();
b=b+10;
}
public static void main(String[] args) {
final CyclicBarrier bar = new CyclicBarrier(2);
Thread thread1 = new Thread(new Runnable(){
#Override
public void run()
{
try {
bar.await();
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch ( BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
while(true)
print();
}
});
Thread thread2 = new Thread(new Runnable(){
#Override
public void run()
{try {
bar.await();
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
while(true)
getb();
}
});
thread1.start();
thread2.start();
}
}
You can't create a deadlock with a single barrier. The idea behind a deadlock is to have (at least) two threads, each one holding a different lock and attempting to take a lock on the other one. E.g., consider this simple example:
public class TwoLockRunnable implements Runnable {
private Lock lockInConstructor;
private Lock lockInRuntime;
public TwoLockThread(Lock lockInConstructor, Lock lockInRuntime) {
this.lockInConstructor = lockInConstructor;
this.lockInRuntime = lockInRuntime;
this.lockInConstructor.lock();
}
#Override
public void run() {
lockInRuntime.lock();
System.out.println("After the lock in run()");
}
public static void main(String[] args) {
Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();
TwoLockRunnable runnable1 = new TwoLockThread(lock1, lock2);
TwoLockRunnable runnable2 = new TwoLockThread(lock2, lock1);
new Thread(runnable1).start();
new Thread(runnable2).start();
}
}
The first thread locks lock1 in its constructor and the second locks lock2 in its constructor. The first thread then tries to lock lock2 when its run - but it can't since lock is held by the other thread. Similarly, the second thread attempts to lock lock1 when its run, and fails for the same reason. Thus, you get a deadlock, and the message "After the lock in run()" is never printed.
like Mureinik's, this is the 'synchronized' demo:
public class DeadLockAATest {
static void methodA(DeadLockAATest d1, DeadLockAATest d2) {
synchronized (d1) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (d2) {
System.out.println("\t\t\tmethodA:" + Thread.currentThread().getName());
}
}
}
public static void main(String[] args) {
DeadLockAATest d1 = new DeadLockAATest(), d2 = new DeadLockAATest();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("t1-start:" + Thread.currentThread().getName());
methodA(d1, d2);
System.out.println("t1-end:" + Thread.currentThread().getName());
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("t2-start:" + Thread.currentThread().getName());
methodA(d2, d1);
System.out.println("t2-end:" + Thread.currentThread().getName());
}
});
t1.start();
t2.start();
System.out.println("deadlock...");
}
}
the deadlock output(just one contion, maybe t2 starts first):
t1-start:Thread-0
deadlock...
t2-start:Thread-1
you can replace
methodA(d2, d1);
to
methodA(d1, d2);
and this will output:
t1-start:Thread-0
t2-start:Thread-1
deadlock...
methodA:Thread-0
t1-end:Thread-0
methodA:Thread-1
t2-end:Thread-1
and this is not deadlock, hope to help you.
I have two thread classes: one that prints numbers from 0 to 9, and another from 100 to 109. What I want is to make the first thread wait for the other one to finish. For this, I used the join() method, but it's not working. Please tell me where I'm going wrong:
//demonstrates the use of join() to wait for another thread to finish
class AThread implements Runnable {
Thread t;
AThread() {
t = new Thread(this);
}
public void run() {
try {
for (int i=0; i<10; i++) {
System.out.println(i);
Thread.sleep(10);
}
} catch (InterruptedException e) {
System.out.println(t + " interruped.");
}
}
public void halt(Thread th) {
try {
th.join();
} catch (InterruptedException e) {
System.out.println(t + " interruped.");
}
}
}
//a different thread class (we distinguish threads by their output)
class BThread implements Runnable {
Thread t;
BThread() {
t = new Thread(this);
}
public void run() {
try {
for (int i=100; i<110; i++) {
System.out.println(i);
Thread.sleep(10);
}
} catch (InterruptedException e) {
System.out.println(t + " interruped.");
}
}
}
public class WaitForThread {
public static void main(String[] args) {
AThread t1 = new AThread();
BThread t2 = new BThread();
t1.t.start();
t1.halt(t2.t); //wait for the 100-109 thread to finish
t2.t.start();
}
}
You call join on the thread before it has started. That doesn't work; in that case, join will return immediately, it's not going to wait until the other thread has started and stopped later. You can see this in the API documentation:
Thread.join()
This implementation uses a loop of this.wait calls conditioned on this.isAlive.
Thread.isAlive()
Tests if this thread is alive. A thread is alive if it has been started and has not yet died.
Reorder the statements in your main method
t1.t.start();
t2.t.start();
t1.halt(t2.t); //wait for the 100-109 thread to finish
edit to answer your questions in the comments:
If you want the thread in AThread to wait for the thread in BThread to finish before doing its job, then you'll need to call join in AThread.run, and change your main method:
class AThread implements Runnable {
Thread t;
Thread threadToWaitFor;
AThread(Thread threadToWaitFor) {
t = new Thread(this);
this.threadToWaitFor = threadToWaitFor;
}
public void run() {
// First wait for the other thread to finish
threadToWaitFor.join();
// ...
}
// ...
}
public class WaitForThread {
public static void main(String[] args) {
BThread t2 = new BThread();
AThread t1 = new AThread(t2.t);
t2.t.start();
t1.t.start();
}
}
Assume that one thread prints "Hello" and another prints "World". I have done it successfully for one time, as follows:
package threading;
public class InterThread {
public static void main(String[] args) {
MyThread mt=new MyThread();
mt.start();
synchronized(mt){
System.out.println("Hello");
try {
mt.wait();
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread extends Thread{
public void run(){
synchronized(this){
System.out.println("World!");
notify();
}
}
}
How do I do it for multiple time printing, say for 5 times? I tried putting for loop around the synchronized block, but of no use.
Here being two interdependent threads, we need two synchronizing objects. they could be one of many things. one integer, another object; one Boolean another object; both object; both semaphores and so on. the synchronization technique could be either Monitor or Semaphore any way you like, but they have to be two.
I have modified your code to use semaphore instead of Monitor. The Semaphore works more transparently. You can see the acquire and release happening. Monitors are even higher constructs. Hence Synchronized works under the hood.
If you are comfortable with the following code, then you can convert it to use Monitors instead.
import java.util.concurrent.Semaphore;
public class MainClass {
static Semaphore hello = new Semaphore(1);
static Semaphore world = new Semaphore(0);
public static void main(String[] args) throws InterruptedException {
MyThread mt=new MyThread();
mt.hello = hello;
mt.world = world;
mt.start();
for (int i=0; i<5; i++) {
hello.acquire(); //wait for it
System.out.println("Hello");
world.release(); //go say world
}
}
}
class MyThread extends Thread{
Semaphore hello, world;
public void run(){
try {
for(int i = 0; i<5; i++) {
world.acquire(); // wait-for it
System.out.println(" World!");
hello.release(); // go say hello
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadSeq {
Object hello = new Object();
Object world = new Object();
public static void main(String[] args) throws InterruptedException {
for(int i=0; i<6;i++){
Runnable helloTask = new Runnable(){
#Override
public void run(){
new ThreadSeq().printHello();
}
};
Runnable worldTask = new Runnable(){
#Override
public void run(){
new ThreadSeq().printWorld();
}
};
Thread t1 = new Thread(helloTask);
Thread t2 = new Thread(worldTask);
t1.start();
t1.join();
t2.start();
t2.join();
}
}
public void printHello(){
synchronized (hello) {
System.out.println("Hello");
}
}
public void printWorld(){
synchronized (world) {
System.out.println("World");
}
}
}
The goal here is to synchronize threads so that when one is done it notify the other. If I have to make it, it would be 2 threads executing the same code with different data. Each thread has its own data ("Hello" and true to T1, "World" and false to t2), and share a variable turn plus a separate lock object.
while(/* I need to play*/){
synchronized(lock){
if(turn == myturn){
System.out.println(mymessage);
turn = !turn; //switch turns
lock.signal();
}
else{
lock.wait();
}
}
}
Before you start trying to get it to work five times you need to make sure it works once!
Your code is not guaranteed to always print Hello World! - the main thread could be interrupted before taking the lock of mt (note that locking on thread objects is generally not a good idea).
MyThread mt=new MyThread();
mt.start();
\\ interrupted here
synchronized(mt){
...
One approach, that will generalise to doing this many times, is to use an atomic boolean
import java.util.concurrent.atomic.AtomicBoolean;
public class InterThread {
public static void main(String[] args) {
int sayThisManyTimes = 5;
AtomicBoolean saidHello = new AtomicBoolean(false);
MyThread mt=new MyThread(sayThisManyTimes,saidHello);
mt.start();
for(int i=0;i<sayThisManyTimes;i++){
while(saidHello.get()){} // spin doing nothing!
System.out.println("Hello ");
saidHello.set(true);
}
}
}
class MyThread extends Thread{
private final int sayThisManyTimes;
private final AtomicBoolean saidHello;
public MyThread(int say, AtomicBoolean said){
super("MyThread");
sayThisManyTimes = say;
saidHello = said;
}
public void run(){
for(int i=0;i<sayThisManyTimes;i++){
while(!saidHello.get()){} // spin doing nothing!
System.out.println("World!");
saidHello.set(false);
}
}
}
This is in C:
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t hello_lock, world_lock;
void printhello()
{
while(1) {
pthread_mutex_lock(&hello_lock);
printf("Hello ");
pthread_mutex_unlock(&world_lock);
}
}
void printworld()
{
while(1) {
pthread_mutex_lock(&world_lock);
printf("World ");
pthread_mutex_unlock(&hello_lock);
}
}
int main()
{
pthread_t helloThread, worldThread;
pthread_create(&helloThread,NULL,(void *)printhello,NULL);
pthread_create(&helloThread,NULL,(void *)printhello,NULL);
pthread_join(helloThread);
pthread_join(worldThread);
return 0;
}
There are two thread and both has its own data ("Hello" and true to ht, "World" and false to wt), and share a variable objturn.
public class HelloWorldBy2Thread {
public static void main(String[] args) {
PrintHelloWorld hw = new PrintHelloWorld();
HelloThread ht = new HelloThread(hw);
WorldThread wt = new WorldThread(hw);
ht.start();
wt.start();
}
}
public class HelloThread extends Thread {
private PrintHelloWorld phw;
private String hello;
public HelloThread(PrintHelloWorld hw) {
phw = hw;
hello = "Hello";
}
#Override
public void run(){
for(int i=0;i<10;i++)
phw.print(hello,true);
}
}
public class WorldThread extends Thread {
private PrintHelloWorld phw;
private String world;
public WorldThread(PrintHelloWorld hw) {
phw = hw;
world = "World";
}
#Override
public void run(){
for(int i=0;i<10;i++)
phw.print(world,false);
}
}
public class PrintHelloWorld {
private boolean objturn=true;
public synchronized void print(String str, boolean thturn){
while(objturn != thturn){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(str+" ");
objturn = ! thturn;
notify();
}
}
In simple way we can do this using wait() and notify() without creating any extra object.
public class MainHelloWorldThread {
public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
Thread t1 = new Thread(() -> {
try {
helloWorld.printHello();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
helloWorld.printWorld();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// printHello() will be called first
t1.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
}
}
class HelloWorld {
public void printHello() throws InterruptedException {
synchronized (this) {
// Infinite loop
while (true) {
// Sleep for 500ms
Thread.sleep(500);
System.out.print("Hello ");
wait();
// This thread will wait to call notify() from printWorld()
notify();
// This notify() will release lock on printWorld() thread
}
}
}
public void printWorld() throws InterruptedException {
synchronized (this) {
// Infinite loop
while (true) {
// Sleep for 100ms
Thread.sleep(100);
System.out.println("World");
notify();
// This notify() will release lock on printHello() thread
wait();
// This thread will wait to call notify() from printHello()
}
}
}
}