Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何定义两个线程之间的执行顺序?_Java_Multithreading_Synchronization - Fatal编程技术网

Java 如何定义两个线程之间的执行顺序?

Java 如何定义两个线程之间的执行顺序?,java,multithreading,synchronization,Java,Multithreading,Synchronization,螺纹1打印A1 A2 A3。螺纹2打印B1 B2 B3。我想写一个程序,确保当两个线程都运行时,输出将是A1 B1 A2 B2 A3 B3。到目前为止,我已经提出了以下方案。请让我知道如何简化? 我们能用更少的信号量吗? 这可以通过使用wait()notify()实现吗 }如果您确保只有一个线程执行methodA,另一个线程执行methodB,则可以使用两个信号量。当您打印A1时,您为T2提供了打印B1的可能性。然后需要等待打印A2才能继续 Semaphore aPrintDone = ne

螺纹1打印A1 A2 A3。螺纹2打印B1 B2 B3。我想写一个程序,确保当两个线程都运行时,输出将是A1 B1 A2 B2 A3 B3。到目前为止,我已经提出了以下方案。请让我知道如何简化? 我们能用更少的信号量吗? 这可以通过使用wait()notify()实现吗


}如果您确保只有一个线程执行
methodA
,另一个线程执行
methodB
,则可以使用两个信号量。当您打印
A1
时,您为
T2
提供了打印
B1
的可能性。然后需要等待打印
A2
才能继续

  Semaphore aPrintDone = new Semaphore(0);
  Semaphore bPrintDone= new Semaphore(0);

/**
 * methodA prints : A1 A2 A3
 */
 public void methodA() {
     try {
         System.out.println("A1");
         aPrintDone.release();
         bPrintDone.acquire();
         System.out.println("A2");
         aPrintDone.release();
         bPrintDone.acquire();
         System.out.println("A3");
         aPrintDone.release();
    }catch (InterruptedException e1) {
         e1.printStackTrace();
    }
  }

  /**
   * methodB prints : B1 B2 B3 
  */
  public void methodB() {
    try {
        aPrintDone.acquire();
        System.out.println("B1");
        bPrintDone.release();
        aPrintDone.acquire();
        System.out.println("B2");
        bPrintDone.release();
        System.out.println("B3");
    }catch (InterruptedException e1) {
        e1.printStackTrace();
    }
}

也可以使用
wait()
notify()
解决此问题。考虑<代码> WAITE()/CODE >意味着线程将等待直到满足某个条件(在这种情况下,B打印,对于<代码> T1 ;以及线程的一次打印<代码> T2< /代码>)。因此,当
System.out.println
完成时,它可以
notify()
另一个线程开始打印。我更喜欢信号量解析,但是使用这些方法来解决它是可以的。

回答
等待通知
问题:是的,这是可能的。它甚至只适用于一个锁对象。但代码既不可读也不“安全”。代码要求在
methodB()
之前执行
methodA()
,否则程序将死锁

public class Synchronization {

    synchronized public void methodA() {
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A1");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A2");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A3");
        this.notify();
    }

    synchronized public void methodB() {
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B1");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B2");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B3");
    }

    public static void main(String... args) throws InterruptedException {
        Synchronization ts = new Synchronization();
        Thread t1 = new Thread(ts::methodA);
        Thread t2 = new Thread(ts::methodB);

        t1.start(); // If you switch those lines,
        t2.start(); // the program will deadlock.

        t1.join();
        t2.join();
        System.out.println("test done");
    }
}

删除了try-catch以提高可读性,但没有它就无法编译。错误的方法。请不要使用“不编译”代码。当人们告诉你:“你的代码做得不对”时,问一下如何解决这个问题。然后把它修好。不要只是盲目地删除代码。人们会很快因为你提出不编译代码而责骂你。一开始还不是很清楚,那只是Java样板。要让它编译,请将每个方法的主体包含在一个try/catch块中。中断是一个明确的请求,要求线程停止它正在做的任何事情并优雅地退出。你永远不应该忽视中断异常,继续下去,就好像什么都没发生一样;这样做会使您的线程成为无法干净终止的流氓线程。@xTrollxDudex它不必要地不清楚,并且表示的代码应该
抛出
和/或在更高级别上包装。Java不会强迫人们编写比Java要求更复杂的代码。。仅仅因为Java IDE想要“自动包装”检查过的异常,并不意味着它们应该被盲目地尊重:}我会在审查中拒绝这样的代码,这一点特别重要,因为这样可以更快地判断有问题的代码..太好了。这是有效的,信号量的数量也减少了。你能评论一下这是否也可以用wait notify来完成吗?@AmolBinwade我更新了我的答案来回答
wait notify
问题。如果methodA首先执行,程序将被卡住,因为T1将永远等待。@AmolBinwade
methodA()
中的第一个
wait()
由立即
notify()发布
methodB()中的
。请您指定您在
method1()
中看到死锁的时间
wait()
?对..我错过了…这应该可以…将尝试并确认。谢谢..但是t2.start()之前的序列t1.start()不能保证methodA将在methodB之前开始执行。这取决于调度程序将首先执行哪个线程。对吧?没错。这就是为什么我在回答中明确地说,在调用
methodB()
之前必须先调用
methodA()
。您可以通过执行命令,例如,
倒计时闩锁
public class Synchronization {

    synchronized public void methodA() {
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A1");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A2");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A3");
        this.notify();
    }

    synchronized public void methodB() {
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B1");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B2");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B3");
    }

    public static void main(String... args) throws InterruptedException {
        Synchronization ts = new Synchronization();
        Thread t1 = new Thread(ts::methodA);
        Thread t2 = new Thread(ts::methodB);

        t1.start(); // If you switch those lines,
        t2.start(); // the program will deadlock.

        t1.join();
        t2.join();
        System.out.println("test done");
    }
}