简体   繁体   中英

Printing “Hello” and “world” multiple times using two threads in java

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();
            }
        }
    }

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);
        }
    }
}
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");
        }
    }
}

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()
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM