如何使用ExecutorService重新启动先前在Swing应用程序中终止的线程

时间:2019-05-07 08:11:42

标签: java multithreading swing executorservice

我正在创建一个Swing应用程序。它包含一个JFrame,在JFrame中,我添加了一个JButton来启动和停止一些任务。我正在使用相同的JButton启动和停止由ExecutorService执行的线程任务。

在单击“开始”按钮时,将执行线程,并且按钮标签将更改为“停止”,而在单击“停止”按钮时,将停止所有线程(我已经使用ExecutorService shutdownNow()方法完成了此操作)和按钮标签将再次更改为“开始”,但不会关闭该应用程序。 现在,如果我再次单击“开始”按钮,应用程序将被挂起,则不会从头开始重新启动线程。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MultipleThreads {
    public static ExecutorService executor = Executors.newFixedThreadPool(4);

    public static void main(String[] args) {
        JFrame frame = new JFrame("Stop Thread");
        frame.setSize(200,200);
        frame.setLocationRelativeTo(null);
        frame.setLayout(null);
        JPanel panel = new JPanel();
        panel.setBounds(5,5,150,150);
        panel.setLayout(null);
        JButton btn = new JButton("Start");
        btn.setBounds(10,10,80,25);

        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                if (btn.getText().equals("Start")) {
                    btn.setText("Stop");
                    MultipleThreads2 runThreads = new MultipleThreads2();
                    runThreads.runThreadMethod();
                } else if (btn.getText().equals("Stop")) {
                    try {
                        if (!executor.awaitTermination(800, TimeUnit.MILLISECONDS)) {
                            executor.shutdownNow();
                        } 
                    } catch (InterruptedException e) {
                        executor.shutdownNow();
                    }

                    btn.setText("Start");
                }
            }
        });
        panel.add(btn);
        frame.add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

class MultipleThreads2 {
    public volatile boolean flag = true;

    public void stopRunning() {
        flag = false;
    }

    public MultipleThreads2() {
        while (flag) {
            try {
                MultipleThreads.executor.submit(t1);
                MultipleThreads.executor.submit(t2);
                flag = false;
                System.out.println(t1.isAlive());
            } catch (Exception e) {

            }
        }
    }

    public void runThreadMethod() {
        flag = true;
        while (flag) {
            try {
                MultipleThreads.executor.submit(t3);
                MultipleThreads.executor.submit(t4);
                    flag = false;
            } catch (Exception e) {

            }
        }
    }

    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println("From t1 Thread");
                    Thread.sleep(1000);
                }
            } catch (Exception e) {

            }
        }
    });

    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println("From t2 Thread");
                    Thread.sleep(500);
                }
            } catch (Exception e) {

            }
        }
    });

    Thread t3 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println("From t3 Thread");
                    Thread.sleep(500);
                }
            } catch (Exception e) {

            }
        }
    });

    Thread t4 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println("From t4 Thread");
                    Thread.sleep(500);
                }
            } catch (Exception e) {

            }
        }
    });
}

预期:第二次单击“开始”按钮时,应从头开始重新启动所有线程。

1 个答案:

答案 0 :(得分:1)

这里:

public static ExecutorService executor = Executors.newFixedThreadPool(4);

您一次创建了该线程池。稍后,您在打电话

executor.shutdownNow();

换句话说:您正在启动汽车,在某个时候,您将汽车停下,下车,然后将其着火。然后您问自己:“好吧,我怎么能用那辆车开车回家?”。好吧,你不能。你只是把它放火了。

这是同一件事:关闭服务时,它消失

长话短说,简单(不一定是理想的)解决方案是:

public static ExecutorService executor = null;

及以后:

if (executor == null) 
  executor = Executors.newFixedThreadPool(4);

executor.shutdownNow();
executor = null;

换句话说:你开车开车,着火了,然后又买了一辆新的,制造另一辆车,然后着火了。

当然,设置为null并进行检查的方法可能会导致各种问题。这样做会更好一些:

  executor.shutdownNow();
  executor = Executors.newFixedThreadPool(4);

含义:而不是将执行程序保留为空,而只是在告诉“最后一个”关闭后,您只需创建一个新实例即可。因此,从理论上讲,每当执行程序习惯于提交任务或关闭执行程序时,您就是在与当前“有效”实例进行对话。