Java 如何定义两个线程之间的执行顺序?
螺纹1打印A1 A2 A3。螺纹2打印B1 B2 B3。我想写一个程序,确保当两个线程都运行时,输出将是A1 B1 A2 B2 A3 B3。到目前为止,我已经提出了以下方案。请让我知道如何简化? 我们能用更少的信号量吗? 这可以通过使用wait()notify()实现吗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
}如果您确保只有一个线程执行
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将永远等待。@AmolBinwademethodA()
中的第一个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");
}
}