Java 像这样运行几个线程会有什么后果?

Java 像这样运行几个线程会有什么后果?,java,multithreading,swing,swingworker,Java,Multithreading,Swing,Swingworker,我需要同时运行2个线程(如果两个线程同时被请求的话),否则如果其中一个单独被请求,那么每个线程都需要自己运行。每个线程将负责从自己的唯一传感器(实际硬件)获取自己的唯一读数,我需要每个线程查询其传感器,直到检测到某个值。当且仅当检测到此值时,线程才会停止并退出 我还需要一种方法让我的软件毫无疑问地知道两个线程都已停止并退出/完成了它们的任务,并从硬件检测到了各自的值。当且仅当两个线程都检测到它们的值时,才应调用我的onFinish()方法。在我的代码中,我使用了第三个线程来监视和使用整数值。调用

我需要同时运行2个线程(如果两个线程同时被请求的话),否则如果其中一个单独被请求,那么每个线程都需要自己运行。每个线程将负责从自己的唯一传感器(实际硬件)获取自己的唯一读数,我需要每个线程查询其传感器,直到检测到某个值。当且仅当检测到此值时,线程才会停止并退出

我还需要一种方法让我的软件毫无疑问地知道两个线程都已停止并退出/完成了它们的任务,并从硬件检测到了各自的值。当且仅当两个线程都检测到它们的值时,才应调用我的onFinish()方法。在我的代码中,我使用了第三个线程来监视和使用整数值。调用onFinish()方法后,整数变量threadCount将重置为0,boolean shouldRun也将重置为0,在onFinish()方法中,boolean shouldRun将重置为false

我想知道我的方法在逻辑上是否可以接受/合理(请注意,我还没有对每个传感器的实际查询进行逻辑分析(可能会使用while循环))。此外,使用我描述的方法会产生什么后果,我的代码如下所示:

private void decreaseThreadCount(){
    threadCount -=1;
}

boolean shouldRun = false;
int threadCount = 0;

public void onStart() {
    System.out.println("START");
    System.out.println("    ");
    System.out.println("START PROGRESS BAR");

    if((customProgressBarL != null || customProgressBarR != null) || (customProgressBarL != null && customProgressBarR != null)){
        shouldRun = true;
    }

    /**TESTING PURPOSES*/

    if (customProgressBarL != null) {
        threadCount += 1;
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <= 100; i++) {
                    try {
                        customProgressBarL.updateProgress(i);
                        customProgressBarL.repaint();
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                try {
                    Thread.sleep(5);
                    decreaseThreadCount();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }).start();
    }

    if (customProgressBarR != null) {
        threadCount += 1;
        new Thread(new Runnable() {
            @Override
            public void run() {

                for (int i = 0; i <= 100; i++) {
                    try {
                        customProgressBarR.updateProgress(i);
                        customProgressBarR.repaint();
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //System.out.println("Thread Count: " + threadCount);
                try {
                    Thread.sleep(5);
                    decreaseThreadCount();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }).start();
    }

    new Thread(new Runnable() {
        @Override
        public void run() {

            while(threadCount >= 0 && shouldRun){
                try {
                    System.out.println("Thread Count: " + threadCount);
                    if(threadCount == 0){
                        onFinish();
                        return;
                    }
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return;
        }
    }).start();

}

您已经在外部(T1、T2、T3)同时启动了所有线程,T3正在等待所有线程完成并执行一些onFinish

相反,您可以在T3中实例化T1和T2。 创建一个具有计数数的倒计时闩锁。 当两个线程都完成任务,然后执行onFinish()时,减少闩锁计数

创建T1/T2的所有逻辑都应该在T3内部

new Thread(new Runnable() {
    @Override
    public void run() {
      int count = 2;
      CountdownLatch latch = new CountdownLatch(count);
      MyThread t1 = new MyThread(latch);
      MyThread t2 = new MyThread(latch);
      t1.start()
      t2.start();
      latch.await();
      onFinish();
    }
}).start();

您已经在外部(T1、T2、T3)同时启动了所有线程,T3正在等待所有线程完成并执行一些onFinish

相反,您可以在T3中实例化T1和T2。 创建一个具有计数数的倒计时闩锁。 当两个线程都完成任务,然后执行onFinish()时,减少闩锁计数

创建T1/T2的所有逻辑都应该在T3内部

new Thread(new Runnable() {
    @Override
    public void run() {
      int count = 2;
      CountdownLatch latch = new CountdownLatch(count);
      MyThread t1 = new MyThread(latch);
      MyThread t2 = new MyThread(latch);
      t1.start()
      t2.start();
      latch.await();
      onFinish();
    }
}).start();

只有一条螺纹可以接触回转组件;你应该这样写:

SwingUtilities.invokeLater(() -> {
    customProgressBarR.updateProgress(i);
    customProgressBarR.repaint();
});

只有一条螺纹可以接触回转组件;你应该这样写:

SwingUtilities.invokeLater(() -> {
    customProgressBarR.updateProgress(i);
    customProgressBarR.repaint();
});

我注意到,在我的方法中有一点是,有时在两个线程都完成后没有调用decreaseThreadCount(),这会导致挂起。不知道如何解决这个问题。首先,您违反了Swing API的单线程特性,有可能出现脏读/写/画图的风险。因为threadCount
threadCount
不是
volatile
,您也有可能读取变量。自由旋转线程(while(threadCount>=0&&shouldlrun){
)是一个坏主意,应该使用监视器锁或类似于
CountDownLatch`的东西来管理。您可能还想阅读一下这个示例。
CountDownLatch
。在我的方法中,我注意到的一件事是有时我的线程数会减少()在两个线程完成后都不会调用,这会导致挂起。不确定如何解决这个问题。首先,您违反了Swing API的单线程特性,可能会导致脏读/写/画图。threadCount不是
volatile
,您也可能会导致脏读变量横倾螺纹(同时(螺纹计数>=0&&shouldRun){
)这是一个坏主意,应该使用监视器锁或类似于
CountDownLatch的东西进行管理`您可能还想阅读一下这篇文章。
CountDownLatch
。如果我将T1和T2放在T3中,这能解决上面提到的所有问题吗?其他人提到的问题是线程计数不是线程安全的。意思是由于争用条件的原因,两个线程读取的值可能是2试图同时递减,现在当前值是1而不是0。为了克服这个问题,我使用了线程安全的倒计时锁存器。T1/T2的线程也应该是这样的。run(){Swing applications(不清楚我们在这里谈论的是swing,但我们应该注意标签)不应该到处打开线程。Swing应用程序应该使用SwingWorkers。为了澄清这一点,我的应用程序是使用Swing编写的,从上面的评论可以看出,如果使用Swing,我不能使用多线程,因为它只用于单线程?我已经实现了您的解决方案,它似乎工作得很好,谢谢!我发布了我的我想知道我是否还必须使用SwingWorkers,而不是像上面看到的那样创建线程?另外,我是否需要使用[code]SwingUtilities.invokeLater(()->{customProgressBarR.updateProgress(I);customProgressBarR.repaint();});[/code]如前所述?如果我将T1和T2放在T3中,这是否解决了上述所有人提到的问题?其他人提到的问题是threadCount不是线程安全的。这意味着由于竞争条件,两个线程读取的值可能是2试图同时递减,而现在当前值是1而不是0。为了克服这一问题,我使用了倒数锁存器,它是线程安全的。T1/T2的线程应该是这样的。run(){Swing应用程序(不清楚我们在这里讨论的是Swing,但我们应该注意标记)不应该到处打开线程。Swing应用程序应该使用SwingWorkers。为了澄清这一点,我的应用程序是使用Swing编写的,从上面的评论可以看出,如果使用Swing,我不能使用多线程,因为它只用于单线程?我已经实现了您的解决方案,它似乎工作得很好,谢谢!我发布了我的我想知道我是否仍然需要使用SwingWorkers,而不是像上面看到的那样创建线程?另外,我是否需要使用[code]SwingUtilities.invokeLater(()->{customPro)
SwingUtilities.invokeLater(() -> {
    customProgressBarR.updateProgress(i);
    customProgressBarR.repaint();
});