[英]JFrame freezes when I try to interrupt threads
在本練習中,我有3個類,一個Provider(Thread)不斷提供存儲在LinkedList內的Integer產品,因此我遇到了這個問題。 一旦大小至少達到10,零售商(線程)就可以全部購買。 還有負責協調線程的分發服務器。 產品顯示在JFrame上,然后當我單擊“停止”按鈕時,每個線程都停止,每個零售商都告訴他們購買了多少產品。
編輯:忘了提出問題了,每當我單擊“停止”按鈕時,應用程序凍結,我什至無法關閉JFrame窗口,不明白為什么。
public class Distributor {
private JTextField textfield = new JTextField();
private LinkedList<Integer> productList = new LinkedList<Integer>();
private JFrame frame = new JFrame("Window");
private JButton btn = new JButton("Stop");
private Thread provider = new Thread(new Provider(this));
private LinkedList<Thread> retailerList = new LinkedList<Thread>();
private void addRetailer(int num) {
for (int i = 0; i < num; i++)
retailerList.add(new Thread(new Retailer(i, this)));
}
public Distributor() {
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(textfield);
frame.add(btn, BorderLayout.SOUTH);
addRetailer(2);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
provider.interrupt();
provider.join();
System.out.println(provider.isAlive());
for (Thread t : retailerList) {
t.interrupt();
t.join();
System.out.println(t.isAlive());
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
});
}
public void execute() {
frame.setVisible(true);
provider.start();
for (Thread t : retailerList)
t.start();
}
// Keeps providing products, and notifies retailers when there are 10 products
public synchronized void provide(int product) {
textfield.setText(productList.toString());
productList.add(product);
if (productList.size() == 10)
notifyAll();
}
// Sells all the products if there are at least 10 to sell.
public synchronized int sell() throws InterruptedException {
while (productList.size() < 10)
wait();
int total = productList.size();
notifyAll();
textfield.setText(productList.toString());
productList.clear();
return total;
}
}
Provider類:
public class Provider implements Runnable {
private Distributor distribuidor;
private int total = 0;
public Provider(Distributor distribuidor) {
super();
this.distribuidor = distribuidor;
}
@Override
public void run() {
while (!Thread.interrupted()) {
try {
distribuidor.provide((int) (Math.random() * 10) + 1);
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
}
System.out.println("Provider Interrupted");
}
}
零售商類別:
public class Retailer implements Runnable {
private Distributor distributor;
private int total = 0;
private int id;
public Retailer(int id, Distributor distributor) {
super();
this.id = id;
this.distributor = distributor;
}
@Override
public void run() {
while (!Thread.interrupted()) {
try {
total += distributor.sell();
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
}
System.out.println("Retailer id: " + id + " bought: " + total + " products");
}
}
和主類:
public class Main {
public static void main(String[] args) {
Distributor distributor = new Distributor();
distributor.execute();
}
}
問題是您的Thread
實際上永遠不會停止,並且EDT也被阻止。
我建議您使用布爾值來停止Provider
內的無限循環。
class Provider implements Runnable {
private Distributor distribuidor;
private int total = 0;
private boolean isRunning = true;
public void setIsRunning(boolean bool){
isRunning = bool;
}
public Provider(Distributor distribuidor) {
super();
this.distribuidor = distribuidor;
}
@Override
public void run() {
while (isRunning) {
try {
distribuidor.provide((int) (Math.random() * 10) + 1);
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
}
System.out.println("Provider Interrupted");
}
}
在您的Distributor
類中,更改以下內容:
private Provider pro = new Provider(this);
private Thread provider = new Thread(pro);
和
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
pro.setIsRunning(false);
provider.interrupt();
provider.join();
System.out.println(provider.isAlive());
for (Thread t : retailerList) {
t.interrupt();
t.join();
System.out.println(t.isAlive());
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
});
不要在循環內捕獲InterruptedException,而應將循環放入try {...}中
提供者類別:
public class Provider implements Runnable {
private Distributor distribuidor;
private int total = 0;
public Provider(Distributor distribuidor) {
super();
this.distribuidor = distribuidor;
}
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
distribuidor.provide((int) (Math.random() * 10) + 1);
Thread.sleep(10);
}
} catch (InterruptedException interruptedException) {
}
System.out.println("Provider Interrupted");
}
}
零售商類別:
public class Retailer implements Runnable {
private Distributor distributor;
private int total = 0;
private int id;
public Retailer(int id, Distributor distributor) {
super();
this.id = id;
this.distributor = distributor;
}
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
total += distributor.sell();
Thread.sleep(10);
}
} catch (InterruptedException interruptedException) {
}
System.out.println("Retailer id: " + id + " bought: " + total + " products");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.