I need to run 2 threads simultaneously (on occasion if both have been requested together) otherwise if either one is requested solo then each thread needs to run on its own. Each thread will be responsible for taking its own unique reading from its own unique transducer (actual hardware), I need each thread to query its transducer until a certain value is detected. If and only if this value is detected should the thread stop and exit.
I also need a way for my software to know without a doubt that both threads have stopped and exited/completed their task and detected their respective values from the hardware. If and only if both threads detect their values should my onFinish() method be called. In my code, I used a third thread to do this monitoring and the use of integer values. The integer variable threadCount is reset to 0 once my onFinish() method is called and so is my boolean shouldRun which is reset to false within the onFinish() method.
Was wondering if my approach is acceptable/sound logically ( please note I havent done the logic yet for the actual query of each transducer (likely will use a while loop)) also what are the consequences for using the approach I described, my code is as seen below:
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();
}
[Edit 1] After reading through the advice given and a bunch of online documentation I have come up with the following code which seems to work under the cases I have tested so far.
Was wondering if I should still use SwingWorkers or if the modified approach is acceptable?
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();
}
[Edit 2]
I have tried a version where I use SwingWorker instead of my Threads, below is the code and it works just as well as the code in [Edit 1] (as far as I can tell at least). What are the pros/cons of each approach?
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;
}
}
I initiate everything as follows in my onStart() method by calling the execute() method:
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();
}