Java:在同一线程上多次调用join()?

Java:在同一线程上多次调用join()?,java,multithreading,Java,Multithreading,我有线程A、B和C。我同时启动A和B,线程C将在A和B结束后执行它的逻辑。我还想在A结束后执行其他操作,在线程B结束后执行不同的操作 所以我这样设计: final Thread a = new Thread() { @Override public void run() { // do something } }; final Thread b = new Thread() { @Override public void run() {

我有线程A、B和C。我同时启动A和B,线程C将在A和B结束后执行它的逻辑。我还想在A结束后执行其他操作,在线程B结束后执行不同的操作

所以我这样设计:

final Thread a = new Thread() {
    @Override
    public void run() {
        // do something
    }
};

final Thread b = new Thread() {
    @Override
    public void run() {
        // do something
    }
};

AbstractAction x = new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        a.start();
        try {
            a.join();
        } catch (InterruptedException e1) {
        }

        // do some other things
    }
};

AbstractAction y = new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        b.start();
        try {
            b.join();
        } catch (InterruptedException e1) {
        }

        // do some more different things
    }
};

Thread c = new Thread() {
    @Override
    public void run() {
        try {
            a.join();
            b.join();
        } catch (InterruptedException e) {
        }

        // do things after a and b ends
    }
};
我担心我在这里做错了什么,因为我找不到关于在同一个线程上多次调用join的任何提示

另一方面,我不知道如何才能以其他方式实现我想要的。我可以用它

while (a.isAlive() || b.isAlive()) {
    // do nothing
}
// do things after a and b ends
但对我来说,情况更糟

---更新1---

如果你问为什么要做这样的事

有两个按钮b1和b2

x、 performAction在b1上显示指示灯,而在后台我正在从DB加载数据,这是在线程a中完成的。 y、 performAction为b2做了类似的事情,但加载数据线程b的不同部分

只要数据正在加载,将启动和加入操作执行就会导致显示指示器。数据加载完成后,指示器消失

还有其他行动。在数据加载完成之前,按钮被禁用,用户无法单击它


关键是启用这两个按钮,让用户仅在从DB加载两部分数据后单击它们。这一点还允许单独显示指示器-如果线程a在线程b之前完成,则没有必要在按钮b1上显示指示器。

在一个线程上多次连接是安全的

此外,我还注意到一些不太正确的地方,如果您希望这段代码在两个线程都处于活动状态时不执行任何操作,为什么不

while (!a.isAlive() && !b.isAlive()) {
    // do things
    break;
}
这对我来说比创建一个什么都不做的循环更有意义


编辑:添加一个中断,使循环在执行一次后停止

在一个线程上多次连接是安全的

此外,我还注意到一些不太正确的地方,如果您希望这段代码在两个线程都处于活动状态时不执行任何操作,为什么不

while (!a.isAlive() && !b.isAlive()) {
    // do things
    break;
}
这对我来说比创建一个什么都不做的循环更有意义


编辑:添加一个中断,使循环在执行一次后停止

考虑此代码会发生什么:

a.join();
b.join();
proceed();
两个螺纹都可能失效,请立即继续; a死,b活:封锁第二行直到b死; a活着,b死了:阻塞第一行直到a死; 都是活的:在第一行阻塞直到a死,然后根据需要阻塞直到b死。 所有四种情况都具有以下不变量:


到达“继续”后,a和b都死机,但不早于。请考虑此代码可能发生的情况:

a.join();
b.join();
proceed();
两个螺纹都可能失效,请立即继续; a死,b活:封锁第二行直到b死; a活着,b死了:阻塞第一行直到a死; 都是活的:在第一行阻塞直到a死,然后根据需要阻塞直到b死。 所有四种情况都具有以下不变量:

一旦到达“继续”,但不早于,a和b都死机。

请参阅上的JavaDoc

。。。使用this.wait的循环以this.isAlive为条件调用

因此,您可以安全地多次调用join,因为死线程总是为isAlive设置false

也可以恢复线程

多次启动线程是不合法的。特别是,线程一旦完成执行,就不能重新启动

请参阅上的JavaDoc

。。。使用this.wait的循环以this.isAlive为条件调用

因此,您可以安全地多次调用join,因为死线程总是为isAlive设置false

也可以恢复线程

多次启动线程是不合法的。特别是,线程一旦完成执行,就不能重新启动


只要两个线程都在工作,那么这不会以重复“//do things”结束吗?我只想“//do things”一次。如果任何线程仍处于活动状态,它也将无法执行任何操作。@MarkoTopolnik实际上这就是我代码的目的-等待两个线程都已死亡,然后再执行其他操作。它与GUI相关…@Druedain,答案中的代码的作用是检查一次,如果线程仍然处于活动状态,则什么也不做。无需等待,无需重试。只要两个线程都在工作,这不会导致重复“//do things”吗?我只想“//do things”一次。如果任何线程仍处于活动状态,它也将无法执行任何操作。@MarkoTopolnik实际上这就是我代码的目的-等待两个线程都已死亡,然后再执行其他操作。它与GUI相关…@Druedain,答案中的代码的作用是检查一次,如果线程仍然处于活动状态,则什么也不做。没有等待,没有重试。这正是我想要实现的:所以。。。这似乎回答了你的问题?这正是我想要实现的:所以。。。这似乎回答了你们的问题?所以我得到了问题的答案,所以现在我明白了,我必须更准确地问他们:。也许下次会更幸运。我只是想
ted想知道这是否是一个好的设计,或者我应该尝试更精确的Java线程功能。但是知道它是安全的也是非常有帮助的。开始一个线程然后在下一行加入它有什么意义?您的actionPerformed方法不妨调用a.run和b.run,以避免创建和销毁线程的开销。@jameslarge我这样做,因为我找不到更好的方法来实现我对线程c的操作。这就是重点!如果您看到一个糟糕的设计,并且知道如何改进它,我仍然在等待这样的评论:。我将使用两个标志和一个条件变量:每个actionPerformed方法将设置一个标志,然后通知条件变量。线程C将等待条件变量,直到两个标志都设置好。所以我得到了问题的答案,所以现在我明白了,我必须更准确地问他们:。也许下次会更幸运。我只是想知道这是否是一个好的设计,或者我应该尝试更精确的Java线程功能。但是知道它是安全的也是非常有帮助的。开始一个线程然后在下一行加入它有什么意义?您的actionPerformed方法不妨调用a.run和b.run,以避免创建和销毁线程的开销。@jameslarge我这样做,因为我找不到更好的方法来实现我对线程c的操作。这就是重点!如果您看到一个糟糕的设计,并且知道如何改进它,我仍然在等待这样的评论:。我将使用两个标志和一个条件变量:每个actionPerformed方法将设置一个标志,然后通知条件变量。线程C将等待条件变量,直到设置了这两个标志。