简体   繁体   English

使用java中的两个线程多次打印“Hello”和“world”

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

Assume that one thread prints "Hello" and another prints "World". 假设一个线程打印“Hello”而另一个打印“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? 如何进行多次打印,比方说5次? 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. 同步技术可以是你喜欢的Monitor或Semaphore,但它们必须是两个。

I have modified your code to use semaphore instead of Monitor. 我已修改您的代码以使用信号量而不是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. 如果我必须这样做,它将是2个线程执行具有不同数据的相同代码。 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. 每个线程都有自己的数据( "Hello"true到T1, "World"false到t2),并共享一个变量turn加上一个单独的锁定对象。

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! 您的代码不能保证始终打印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). - 在获取mt锁之前可能会中断主线程(请注意,锁定线程对象通常不是一个好主意)。

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: 这是在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. 有两个线程,两者都有自己的数据(“Hello”,对于ht,“World”和false为false),并共享一个变量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. 以简单的方式,我们可以使用wait()notify()来完成此操作,而无需创建任何额外的对象。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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