为了账号安全,请及时绑定邮箱和手机立即绑定

如何在退出前安全关闭所有线程

如何在退出前安全关闭所有线程

拉风的咖菲猫 2021-09-29 17:35:10
我有一个启动几个线程的应用程序,最终一个线程可能需要退出整个应用程序,但是其他线程可能处于任务中间,所以我想让它们在退出之前继续当前循环。在下面的示例中,线程 2 不知道线程 1 何时尝试退出,它只是强制一切立即完成。我怎样才能让 Thread2、3 和 4 等在关闭之前完成它们的循环?编辑:为了解决重复的问题:这与父类不能负责操纵关闭的典型情况不同,任何单个线程都必须能够启动关闭。Edit2:我还留下了我最终做的答案,这是已接受答案的实现。class Scratch {    public static void main(String[] args) {        Thread Task1 = new Thread(new Task1());        Task1.start();        Thread Task2 = new Thread(new Task2());        Task2.start();        // ... more threads    }    public class Task1 implements Runnable {        public void run() {            while (true) {                // ...                System.exit(0);                // ...            }        }    }    public class Task2 implements Runnable {        public void run() {            while (true) {                // ...                // I need to know about System.exit(0) to exit my loop                // ...            }        }    }}
查看完整描述

3 回答

?
智慧大石

TA贡献1946条经验 获得超3个赞

您可以使用volatile boolean所有线程将不断检查的变量。如果一个线程将该变量的值设置为false,则所有线程都将看到新值并离开while循环。


说明:volatile变量中的读/写操作是原子的。除此之外,volatile 变量的值不会被缓存,所以所有线程看到的都是相同的值。


class Scratch {


    private static volatile boolean isRunning = true;


    public static void main(String[] args) {

        Thread Task1 = new Thread(new Task1());

        Task1.start();


        Thread Task2 = new Thread(new Task2());

        Task2.start();


        // ... more threads

    }


    public class Task1 implements Runnable {

        public void run() {

            while (isRunning) {

                // ...

                isRunning = false; // let's stop all threads

                // ...

            }

        }

    }


    public class Task2 implements Runnable {

        public void run() {

            while (isRunning) {

                // ...

                // I need to know about System.exit(0) to exit my loop

                // ...

            }

        }

    }

}


查看完整回答
反对 回复 2021-09-29
?
侃侃无极

TA贡献2051条经验 获得超10个赞

自己创建线程被认为是“不好的做法”,您应该考虑使用 ExecutorService。同步应该通过中断线程来完成。


class Scratch {

    private final ExecutorService executorService;

    public Scratch(ExecutorService es) {

       this.executorService = es;

    }

    /** Convience constructor */

    public Scratch() {this(Executors.newCachedThreadPool());}


    public class Task1 implements Callable<Void> {

        public Void call() throws Exception {

            while(true) {

                ...

                executorService.shutdownNow(); // interrupt all running threads

                                               // (including Task1) started by

                                               // given executor service

                if (Thread.interrupted())

                    throw new InterruptedException();

            }

            return null;

        }

     }


     public class Task2 implements Callable<Void> {

         public Void call() throws Exception {

             while(true) {

                 // check if the thread was interrupted, if so throw Exception

                 if (Thread.interrupted())

                     throw new InterruptedException();

             }

             return null;

         }

     }


     public static void main(String ... args) {

         Scratch s = new Scratch();

         s.executorService.submit(new Task1());

         s.executorService.submit(new Task2());

     }

 }



查看完整回答
反对 回复 2021-09-29
?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

除了使用volatile boolean variable实现的方法(这是一个很好的方法)之外,您还可以考虑使用listeners。它们通常在 Android API 中使用。


首先,创建定义侦听器的接口。下面是一个例子:


public interface TaskListener {

    public void onFinish();

}

现在,在您希望收到任务完成通知的类上实现此接口。往下看:


public class Task2 implements Runnable, TaskListener { 

    public void run() { 

        while (!Thread.currentThread().isInterrupted()) { 

            //... 

        } 

    }


    public void onFinish() {

         //perform your exit operations here.

         Thread.currentThread().interrupt();

    } 

}

现在,准备您的主要任务的类以接收侦听器。看一看:


public class Task1 implements Runnable { 

    private ArrayList<TaskListener> listeners = new ArrayList<>();


    public void run() { 

        while (true) { 

            // ... 

            this.finish();

            // ... 

        } 

    } 


    public void addListener (TaskListener listener) {

        this.listeners.add(listener);

    } 


    private void finish() {

        for(TaskListener listener: this.listeners) {

             listener.onFinish();

        } 

    } 

 }

完成所有设置后,现在可以轻松聆听任务的完成情况。往下看:


public static void main(String[] args) { 

    Thread task1 = new Thread(new Task1()); 

    Thread task2 = new Thread(new Task2()); 


    task1.addListener(task2);

    task1.start();

    task2.start();

完毕!现在,每次task1.finish()调用时,它的所有侦听器(仅task2在此示例中)都会收到通知(onFinish调用它们的方法)。


注意:TaskListener如果您不想,则没有必要在您的所有任务中实施。这是一个使用lambda 表达式的示例:


public static void main(String[] args) { 

    Thread task1 = new Thread(new Task1()); 

    Thread task2 = new Thread(new Task2()); 


    task1.addListener(() -> {

        //this entire block will be called when task1 finishes

        task2.interrupt();

    });


    task1.start();

    task2.start();

注2:我在手机上写了这个答案。虽然我修改了几次代码,看起来还可以,但我要回家才能测试它


查看完整回答
反对 回复 2021-09-29
  • 3 回答
  • 0 关注
  • 508 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信