Выполнение потока продолжается даже после исключения в Java
У меня есть скелет моих потоков в коде ниже. Я использовал простую защелку обратного отсчета. Я застрял в ситуации, когда у меня есть поток 1 в зависимости от потока 2 для завершения. если нет исключения, код работает правильно. Но шансов на исключение больше. Если исключение происходит в потоке 2 или в каком-либо из потоков, я хочу, чтобы все потоки прекратили свое выполнение. Мои независимые потоки продолжают выполняться даже после исключения. Я также использовал флаг в потоке 1, чтобы проверить, произошло ли исключение в потоке 2, я намеренно поместил исключение деления на ноль в качестве примера для проверки на исключение. Я не могу найти решение этой проблемы. Помогите мне, пожалуйста..!
import java.util.concurrent.CountDownLatch;
public class MainThread extends Thread{
static boolean flag=false;
final static CountDownLatch latch1= new CountDownLatch(1);
final static CountDownLatch latch2= new CountDownLatch(1);
final static CountDownLatch latch3= new CountDownLatch(3);
static MainThread t1;
static MainThread t2;
static MainThread t3;
static MainThread t4;
static MainThread t5;
public static void main(String args[]){
t1 = new MainThread(){
public void run(){
System.out.println("Waiting for Thread 2");
try {
System.out.println("THis iss before the thread 2 starts its for loop.");
latch2.countDown();
t3.start();
t4.start();
t5.start();
System.out.println("waiting for thread 2 to countdown");
latch1.await();
if(flag==true){
System.out.println("successful.");
}
else{
System.out.println("error.");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("All the dependencies resolved.");
System.out.println("Waiting for the remaining threads to complete their work.");
try {
latch3.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("All the threads have finished doing their work. Exiting now...");
}
};
Thread t2 = new MainThread(){
public void run(){
System.out.println("Before Starting for loop");
try {
System.out.println("waiting for thread 1 to countdown latch2");
latch2.await();
System.out.println("Starting for loop");
for(int i=0;i<5;i++){
System.out.println("iteration: "+i);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int x=1/0;
latch1.countDown();
System.out.println("countdown by thread2 for latch 1 done.");
flag=true;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
latch1.countDown();
}
}
};
t3 = new MainThread(){
public void run(){
System.out.println("Running Thread 3");
for(int i=0;i<10;i++){
System.out.println("iteration: "+i+ " "+t3.getName());
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
latch3.countDown();
}
};
t4 = new MainThread(){
public void run(){
System.out.println("Running Thread 4");
for(int i=0;i<10;i++){
System.out.println("iteration: "+i+ " "+t4.getName());
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
latch3.countDown();
}
};
t5 = new MainThread(){
public void run(){
System.out.println("Running Thread 5");
for(int i=0;i<10;i++){
System.out.println("iteration: "+i+ " "+t5.getName());
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
latch3.countDown();
}
};
t1.start();
t2.start();
}
}
Мой вывод:
Before Starting for loop
waiting for thread 1 to countdown latch2
Waiting for Thread 2
THis iss before the thread 2 starts its for loop.
Starting for loop
iteration: 0
waiting for thread 2 to countdown
Running Thread 3
iteration: 0 Thread-2
Running Thread 5
iteration: 0 Thread-4
Running Thread 4
iteration: 0 Thread-3
iteration: 1
iteration: 1 Thread-3
iteration: 1 Thread-2
iteration: 1 Thread-4
iteration: 2
iteration: 2 Thread-3
iteration: 2 Thread-2
iteration: 2 Thread-4
iteration: 3
iteration: 3 Thread-3
iteration: 3 Thread-2
iteration: 3 Thread-4
iteration: 4
iteration: 4 Thread-3
iteration: 4 Thread-4
iteration: 4 Thread-2
iteration: 5 Thread-3
error.
All the dependencies resolved.
Waiting for the remaining threads to complete their work.
Exception in thread "Thread-1" java.lang.ArithmeticException: / by zero
at ThreadProjectStructure.MainThread$2.run(MainThread.java:72)
iteration: 5 Thread-4
iteration: 5 Thread-2
iteration: 6 Thread-3
iteration: 6 Thread-4
iteration: 6 Thread-2
iteration: 7 Thread-3
iteration: 7 Thread-2
iteration: 7 Thread-4
iteration: 8 Thread-3
iteration: 8 Thread-2
iteration: 8 Thread-4
iteration: 9 Thread-3
iteration: 9 Thread-4
iteration: 9 Thread-2
All the threads have finished doing their work. Exiting now...
3 ответа
Что ж, с текущим кодом вам нужно правильно понять вашу перспективу. Пожалуйста, определите переменные защелки самоочевидно, иначе это приведет вас в замешательство. Предполагая, что ваше требование следующее: переходите к другим потокам только в случае успешного выполнения потока 2.
Ниже приведен обновленный код:
import java.util.concurrent.CountDownLatch;
public class MainThread extends Thread{
static boolean flag=false;
final static CountDownLatch waitForThread2ToFinish= new CountDownLatch(1);
final static CountDownLatch waitForStartSignalFromThread1= new CountDownLatch(1);
final static CountDownLatch latchForAllOtherThreads= new CountDownLatch(3);
static MainThread t1;
static MainThread t2;
static MainThread t3;
static MainThread t4;
static MainThread t5;
public static void main(String args[]){
t1 = new MainThread(){
public void run(){
try {
System.out.println("Waiting for Thread 2 to finish");
waitForStartSignalFromThread1.countDown();
waitForThread2ToFinish.await();
if(flag==true){
System.out.println("Successful.");
t3.start();
t4.start();
t5.start();
System.out.println("All the dependencies resolved.");
System.out.println("Waiting for the remaining threads to complete their work.");
try {
latchForAllOtherThreads.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All the threads have finished doing their work. Exiting now...");
}
else{
System.out.println("Error.");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new MainThread(){
public void run(){
System.out.println("Before Starting for loop");
try {
System.out.println("waiting for thread 1 to countdown latch2");
waitForStartSignalFromThread1.await();
System.out.println("Starting for loop");
for(int i=0;i<5;i++){
System.out.println("iteration: "+i);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int x=1/0;
System.out.println("countdown by thread2 for latch 1 done.");
flag=true;
} catch (Exception e) {
e.printStackTrace();
}
finally{
waitForThread2ToFinish.countDown();
}
}
};
t3 = new MainThread(){
public void run(){
System.out.println("Running Thread 3");
for(int i=0;i<10;i++){
System.out.println("iteration: "+i+ " "+t3.getName());
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
latchForAllOtherThreads.countDown();
}
};
t4 = new MainThread(){
public void run(){
System.out.println("Running Thread 4");
for(int i=0;i<10;i++){
System.out.println("iteration: "+i+ " "+t4.getName());
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
latchForAllOtherThreads.countDown();
}
};
t5 = new MainThread(){
public void run(){
System.out.println("Running Thread 5");
for(int i=0;i<10;i++){
System.out.println("iteration: "+i+ " "+t5.getName());
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
latchForAllOtherThreads.countDown();
}
};
t1.start();
t2.start();
}
}
Вы думали об использовании пула потоков? Если вы можете изменить свое требование использовать пул потоков, в случае исключения вы можете принудительно отключить пул, и, следовательно, все потоки будут остановлены.
Java не предоставляет никакого прямого метода для остановки выполнения запущенного потока, но он дал метод для прерывания потока. Тем не менее, не гарантируется остановка выполнения потока, он просто устанавливает для флага прерывания значение true для этого потока, и он зависит от потока, который проверяет флаг и генерирует прерванное исключение. Это единственный изящный способ остановить выполнение потока. Вы можете прервать другой поток, вызвав handle.interrupt()