如何使用 ExecutorService 重新启动先前在 Swing 应用程序中终止的线程
How to restart the threads using ExecutorService which were terminated previously in a Swing application
我正在创建一个 Swing 应用程序。它包含一个 JFrame,在 JFrame 内部,我添加了一个 JButton 来启动和停止一些任务。我正在使用相同的 JButton 来启动和停止由 ExecutorService 执行的线程任务。
当点击 Start 按钮时,线程将被执行并且按钮标签将更改为 Stop,而点击 Stop 按钮将停止所有线程(我使用 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) {
}
}
});
}
预期:第二次单击“开始”按钮时应从头重新启动所有线程。
这里:
public static ExecutorService executor = Executors.newFixedThreadPool(4);
您正在创建该线程池一次。稍后,您打电话给
executor.shutdownNow();
换句话说:你正在启动你的车,然后在某个时刻,你停下车,你下车,然后你点燃了它。然后你问自己:"ok, how can I use that car to drive home?"。好吧,你不能。你只是把它点着了。
同样的事情:当你关闭服务时,它消失了。
长话短说,简单(不一定理想)解决方案是:
public static ExecutorService executor = null;
及以后:
if (executor == null)
executor = Executors.newFixedThreadPool(4);
和
executor.shutdownNow();
executor = null;
换句话说:你开着你的车,你放火,然后你买了一辆新的,再开一次,然后放火。
当然,这种设置为 null 并对其进行检查的方法可能会导致各种问题。这样做会好一点:
executor.shutdownNow();
executor = Executors.newFixedThreadPool(4);
意思是:不要让执行程序为 null,只要 "last one" 被告知关闭,您只需创建一个新实例。因此,从理论上讲,每当执行程序习惯于提交任务或关闭时,您正在与当前的 "valid" 实例对话。
我正在创建一个 Swing 应用程序。它包含一个 JFrame,在 JFrame 内部,我添加了一个 JButton 来启动和停止一些任务。我正在使用相同的 JButton 来启动和停止由 ExecutorService 执行的线程任务。
当点击 Start 按钮时,线程将被执行并且按钮标签将更改为 Stop,而点击 Stop 按钮将停止所有线程(我使用 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) {
}
}
});
}
预期:第二次单击“开始”按钮时应从头重新启动所有线程。
这里:
public static ExecutorService executor = Executors.newFixedThreadPool(4);
您正在创建该线程池一次。稍后,您打电话给
executor.shutdownNow();
换句话说:你正在启动你的车,然后在某个时刻,你停下车,你下车,然后你点燃了它。然后你问自己:"ok, how can I use that car to drive home?"。好吧,你不能。你只是把它点着了。
同样的事情:当你关闭服务时,它消失了。
长话短说,简单(不一定理想)解决方案是:
public static ExecutorService executor = null;
及以后:
if (executor == null)
executor = Executors.newFixedThreadPool(4);
和
executor.shutdownNow();
executor = null;
换句话说:你开着你的车,你放火,然后你买了一辆新的,再开一次,然后放火。
当然,这种设置为 null 并对其进行检查的方法可能会导致各种问题。这样做会好一点:
executor.shutdownNow();
executor = Executors.newFixedThreadPool(4);
意思是:不要让执行程序为 null,只要 "last one" 被告知关闭,您只需创建一个新实例。因此,从理论上讲,每当执行程序习惯于提交任务或关闭时,您正在与当前的 "valid" 实例对话。