gpt4 book ai didi

java - 强制执行打印顺序,但线程在一次迭代后彼此等待

转载 作者:行者123 更新时间:2023-12-03 13:07:55 24 4
gpt4 key购买 nike

我无法解决一个线程在等待另一个问题的麻烦(即使在查看了几个问题后也是如此)。这是我要尝试做的事情:我希望一个线程(称为子线程)在外循环下进行2次迭代打印10次。然后另一个(boss线程)在外循环下进行2次迭代打印100次,前提是子线程排在第一位。它看起来像这样:

Sub Thread- iter = 1
Sub Thread- iter = 2
...
Sub Thread- iter = 10
Boss Thread- iter = 1
Boss Thread- iter = 2
...
Boss Thread- iter = 100

此子线程和老板线程的打印顺序将连续2次(外循环)。
我的实现产生了无法预料的结果,即它打印出子线程的第一次迭代10次然后停止在那里,或者它很少打印出所有语句并通过内循环和外循环运行。我使用 wait()notify()启用线程之间的通信。我不确定是否将 synchronized块放置在错误的位置,或者只是误用了 wait()notify()对。这是代码:
public class Main {

public static void main(String[] args) {
Main ic = new Main();

Thread t1 = new Thread(ic.new Th1(), "Boss Thread-");
Thread t2 = new Thread(ic.new Th2(), "Sub Thread-");

t2.start();
t1.start();
}

// Boss Thread
private class Th1 implements Runnable {

@Override
public void run() {
System.out.println("TH1 RUNS FIRST");
synchronized (Main.class) { // lock outside of outer loop so
// boss thread can pick up the next iteration
for (int i = 0; i < 2; i++) {
// wait, let the sub-thread run first
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}

// print iterations
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter = " + (j + 1));
}
System.out.println("end of boss outer----------------------" + (i + 1));
// wake up sub-thread and let it knows inner-iteration finished
Main.class.notify();
}
}
}
}

// Sub Thread
private class Th2 implements Runnable {

@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (Main.class) { // lock up Th2
// print iterations
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter = " + (j + 1));
}

// wake up other boss thread and let it know inner-iteration finished
Main.class.notify();

// wait for other thread to run
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end of Sub outer---------------------- " + (i + 1));
}
}
}
}
}

需要额外的帮助:有人可以告诉我 synchronized是锁定共享资源的好方法还是其他更好的选择?说 ReentrantLock吗?另外, notify()wait()是实现线程间通信的好方法,还是有更好的方法来使这种错误更容易发生并且效率更高?

最佳答案

经过一番思考和努力,我提出了一个“实现”,可以“满足”我的期望,如问题帖中所述。我对waitnotify对进行了一些更改,并添加了isTh2RunFirst标志来协助两个线程的通信。这是代码:

public class InterThCom {
// flag default to false for checking if sub-thread
// gets the lock first
private boolean isTh2RunFirst = false;

public static void main(String[] args) {
InterThCom itc = new InterThCom();

Thread t1 = new Thread(itc.new Th1(), "Boss-thread-");
Thread t2 = new Thread(itc.new Th2(), "Sub-thread-");

t1.start();
t2.start();
}

private class Th1 implements Runnable {

@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) { // lock up inner-loop

// boss-thread gets the lock first
// wait for sub-thread and let it run;
// otherwise, skip this check
if (isTh2RunFirst == false) {
// wait for sub-thread, if boss-thread gets the lock first
try {
InterThCom.class.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}

// print iteration 100 times
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 100 times

// sub-thread should run already at this point
isTh2RunFirst = true;

// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));

// wake up sub-thread
InterThCom.class.notify();

// wait for sub-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

private class Th2 implements Runnable {

@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) {
// print iteration 10 times
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 10 times

// sub-thread already prints j iteration
isTh2RunFirst = true;

// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));

// wake up boss-thread
InterThCom.class.notify();

// wait for boss-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (InterThCom.class) {
// boss-thread is waiting at the last iteration, so wake it up
InterThCom.class.notify();
}
}
}

}

如果有人想针对这种特定情况或其他一般情况,详细讨论线程通信的“适当”实现(在行业实践和效率方面),我也发布了 Code Review post

关于java - 强制执行打印顺序,但线程在一次迭代后彼此等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53235919/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com