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

时间:2019-01-07 06:35:48

标签: java multithreading swing swingworker

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

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

}

[编辑1]在阅读了给出的建议和大量在线文档之后,我想到了以下代码,该代码似乎可以在到目前为止测试过的情况下使用。

是否想知道我是否仍应使用SwingWorkers或修改后的方法是否可以接受?

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

    /**TESTING PURPOSES*/
    CountDownLatch countDownLatch = new CountDownLatch(2);
    new Thread(new Runnable() {
        @Override
        public void run() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (customProgressBarL != null) {
                        for (int i = 0; i <= 100; i++) {
                            try {
                                customProgressBarL.updateProgress(i);
                                customProgressBarL.repaint();
                                Thread.sleep(50);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    countDownLatch.countDown();
                    return;
                }
            }).start();

            new Thread(new Runnable() {
                @Override
                public void run() {         
                    if(customProgressBarR != null){
                        for (int i = 0; i <= 100; i++) {
                            try {
                                customProgressBarR.updateProgress(i);
                                customProgressBarR.repaint();
                                Thread.sleep(50);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    countDownLatch.countDown();
                    return;
                }
            }).start();
            try{
                countDownLatch.await();
                onFinish();
            } catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }).start();
}

[编辑2]

我尝试了一个使用SwingWorker而不是我的线程的版本,下面是代码,它的作用与[Edit 1]中的代码一样好(至少据我所知)。每种方法的利弊是什么?

 private class MySwingWorker extends SwingWorker<Object, Object> {

    CountDownLatch countDownLatch;
    JCustomProgressBar progressBar;

    public MySwingWorker(CountDownLatch countDownLatch, JCustomProgressBar progressBar){
        this.countDownLatch = countDownLatch;
        this.progressBar = progressBar;
    }

    @Override
    protected Object doInBackground() throws Exception {
        if(progressBar != null){
            for (int i = 0; i <= 100; i++) {
                try {
                    progressBar.updateProgress(i);
                    progressBar.repaint();
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        countDownLatch.countDown();
        return null;
    }
}

private class MySwingWorkerManager extends SwingWorker<Object, Object> {

    CountDownLatch countDownLatch;

    @Override
    protected Object doInBackground() throws Exception {
        this.countDownLatch = new CountDownLatch(2);
        new MySwingWorker(countDownLatch, customProgressBarL).execute();
        new MySwingWorker(countDownLatch, customProgressBarR).execute();
        try{
            countDownLatch.await();
            onFinish();
        } catch (InterruptedException e){
            e.printStackTrace();
        }
        return null;
    }
}

我通过调用execute()方法在onStart()方法中启动以下所有操作:

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

    System.out.println("customProgressBarL is: "+customProgressBarL);
    System.out.println("customProgressBarR is: "+customProgressBarR);

    /**TESTING PURPOSES*/
    new MySwingWorkerManager().execute();
}

2 个答案:

答案 0 :(得分:2)

您已经同时启动了所有线程(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();

答案 1 :(得分:0)

应该只有一个线程可以访问swing组件;你应该这样写:

pd.read_csv(filename).to_sql(tablename, con)