简体   繁体   English

Java多线程:使线程交替执行

[英]Java Multithreading: Make threads execute alternatively

I am completely new to multi threading.我对多线程完全陌生。 Need assistance on the below scenario在以下情况下需要帮助

Scenario:- I want two threads to execute, such that they have to print the word "PingPong" alternatively.场景:- 我想要执行两个线程,这样它们就必须交替打印单词“PingPong”。 This has to happen three 3 times for both threads.对于两个线程,这必须发生 3 次 3 次。

For example:-例如:-

  1. Thread 1 has to print "Ping" and it has to go to wait stage.线程 1 必须打印“Ping”并且它必须进入等待阶段。
  2. Thread 2 has to print "Ping" and it has to go to wait stage as well as notify the other thread.线程 2 必须打印“Ping”,它必须进入等待阶段并通知另一个线程。
  3. Thread 1 has to print "Pong" and it has to go to wait stage as well as notify the other thread.线程 1 必须打印“Pong”,它必须进入等待阶段并通知其他线程。
  4. Thread 2 has to print "Pong" and it has to go to wait stage as well as notify the other thread.线程 2 必须打印“Pong”,它必须进入等待阶段并通知另一个线程。

The same way both the threads has to print the word 3 times in total.同样的方式,两个线程必须总共打印 3 次单词。

Coding below:-下面的编码: -

package com.test.files;

public class MultiThreadingTest2 implements Runnable {
    String lastExecutedThread = "";
    Object lockObj = new Object();
    private void print(String wordToPrint) throws InterruptedException {
        synchronized(lockObj) {
            if(lastExecutedThread.equals(Thread.currentThread().getName())) {
                System.out.println(Thread.currentThread().getName()+" entered wait stage");
                lockObj.wait();
            } else {
                lastExecutedThread = Thread.currentThread().getName();
                System.out.println(Thread.currentThread().getName()+" printed "+wordToPrint);
                lockObj.notifyAll();
            }
        }
    }
    
    public MultiThreadingTest2(Object lock) {
        this.lockObj = lock;
    }
    
    @Override
    public void run() {
        String[] wordArr = {"Ping", "Pong"};
        
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < wordArr.length; j++) {
                try {
                    print(wordArr[j]);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        
        Thread t1 = new Thread(new MultiThreadingTest2(lock), "Thread 1");
        Thread t2 = new Thread(new MultiThreadingTest2(lock), "Thread 2");
    
        t1.start();
        t2.start();
    }
}

But I could see the above code has resulted in deadlock.但是我可以看到上面的代码导致了死锁。 Output as follow:-输出如下: -

Thread 1 printed Ping
Thread 1 entered wait stage
Thread 2 printed Ping
Thread 2 entered wait stage
Thread 1 entered wait stage

I am not sure why this has resulted in deadlock.我不确定为什么这会导致僵局。 Reason because, the variable "lastExecutedThread " is created at class level.原因是,变量“lastExecutedThread”是在类级别创建的。 So it should be stored in heap.所以它应该存储在堆中。 If its a local variable, then we can say that it could be in thread stack, so the other thread may not what value it possess and because of which the thread executing the print function will have the "lastExecutedThread" to its name and it will lead to deadlock.如果它是一个局部变量,那么我们可以说它可能在线程堆栈中,所以另一个线程可能没有它拥有的值,因此执行打印函数的线程将在其名称中包含“lastExecutedThread”,它会导致僵局。

Could you please help on this.你能帮忙吗?

You have to make lastExecutedThread static, otherwise each Thread sees its own instance of it.您必须将lastExecutedThread静态,否则每个Thread都会看到它自己的实例。

Note that if inside the print method lockObj.wait() is called, the wordToPrint passed to this method is never printed.请注意,如果在print方法中lockObj.wait() ,则永远不会打印传递给此方法的wordToPrint You can slightly adapt your code to avoid this: if your print method returns true if printing was successful, and false otherwise.您可以稍微调整您的代码来避免这种情况:如果您的print方法在打印成功时返回true ,否则返回false Then inside your nested for-loop, put your call of print inside a while-loop: while (!print(wordArr[j]));然后在嵌套的 for 循环中,将print调用放入 while 循环中: while (!print(wordArr[j]));

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

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