黑马程序员技术交流社区
标题:
Swing,线程,同步,内部类,等待与唤醒综合到一起的应用...
[打印本页]
作者:
施大勇
时间:
2013-9-28 15:07
标题:
Swing,线程,同步,内部类,等待与唤醒综合到一起的应用...
本帖最后由 施大勇 于 2013-9-28 15:10 编辑
想要达到的目的:
将Swing,线程,同步,内部类,等待与唤醒综合到一起的应用: Swing
窗口中有两个标签,分别标注为启动生产者线程和启动消费者线程,在标签下面分别有两个文本域,用于
显示线程的生产和消费信息,底部提供三个按钮,分别为启动生产和消费按钮及停止两个线程的停止按钮,如果按了两次同一个按钮会重新启动线程。
出现的 : 1,hsplit.setDividerLocation(0.5); //设置了分隔条所在的位置,为什么不成功呢?想要分隔条在分割面板的中间。 2,如查一个线程由标记位进行控制,当它启动后,不执行完,在别处中断它,是束可以在中断的代码后再次启动它,如果可以,就如何启动。 3,第三个问题:可不可以将内部类抽取出来呢?我没抽出来
下面的程序如果不考虑多次按启动按钮是可以的,如果发生了多次按启动按钮则会出现各种异常 。这是我运行时出现的问题。(休眠待待)java.lang.IllegalThreadStateException (直接中断)java.lang.StackOverflowError
package SwingThread;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
public class SwingThreadScXf extends JFrame {
// 主方法主要启动一个窗体
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new SwingThreadScXf().setVisible(true);
}
});
}
// 下面这些组件因为要被线程访问,所以将它们作为成员变量,方便内部类调用。
private JTextArea text_1 = new JTextArea(30, 50);
private JTextArea text_2 = new JTextArea(30, 5);
private JButton button_1 = new JButton("开始生产");
private JButton button_2 = new JButton("开始消费");
private JButton button_3 = new JButton("停止所有线程");
// 构造方法用于生成窗体 以及各组件在窗体中的摆放位置。
public SwingThreadScXf() {
super();
setBounds(100, 100, 500, 300);
setLayout(new BorderLayout());
setTitle("在Swing中演示生产者与消费者线程实例");
Container container = getContentPane();
JScrollPane scroll_Pane = new JScrollPane(text_1);
JScrollPane scrol2_Pane = new JScrollPane(text_2);
JPanel panel_left = new JPanel(new GridLayout(2, 1, 0, 0));
JPanel panel_right = new JPanel(new GridLayout(2, 1, 0, 0));
panel_left.add(new JLabel("生产者线程"));
panel_left.add(scroll_Pane);
panel_right.add(new JLabel("消费者线程"));
panel_right.add(scrol2_Pane);
JSplitPane hsplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
panel_left, panel_right);
hsplit.setDividerLocation(0.5); // 设置了分隔条所在的位置,为什么不成功呢?想要分隔条在分割面板的中间。
container.add(hsplit, BorderLayout.CENTER);
// 为按钮添加事件管理器
button_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
do_button_1_start();
}
});
button_2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
do_button_2_start();
}
});
button_3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
do_close();
}
});
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
panel.add(button_1);
panel.add(button_2);
panel.add(button_3);
container.add(panel, BorderLayout.SOUTH);
}
private Computer computer = new Computer();
private Xf xfz = new Xf(computer);
private Sc scz = new Sc(computer);
Thread t1 = new Thread(scz);
Thread t2 = new Thread(xfz);
protected void do_close() { // 关闭相应的启动线程,应等待到少执行一个循环。
if (t1.isAlive()) {
scz.isstart = false;
/*if (!t1.interrupted()) { // 测试生产线程是否忆中断,若没中断则中断它。
t1.interrupt();
}*/ //启动它会发生 java.lang.StackOverflowError
}
if (t1.isAlive()) {
xfz.isstart = false;
/*if (!t1.interrupted()) { // 测试消费线程是否忆中断,若没中断则中断它。
t1.interrupt();
}*/
}
// 启用它会发生:java.lang.IllegalThreadStateException
// try{Thread.sleep(2000);}catch(Exception e){}//等待线程到少执行了一次循环。
}
// 事件处理方法,启动线程或关闭线程
protected void do_button_2_start() {
if (!t2.isAlive()) { // 判断线程是否启动,没启动的话启动。
openflag(); // 每一次启动前都要对线程标启动的标记进行设置。
t2.start();
} else { // 如果已启动,则关闭它并递归。
do_close();
do_button_2_start();
}
}
private void openflag() {// 重设线程启动的标记为可以启。
scz.isstart = true;
xfz.isstart = true;
}
protected void do_button_1_start() {
if (!t1.isAlive()) { // 判断线程是否启动,没启动的话启动。
openflag(); // 每一次启动前都要对线程标启记的标志进行设置。
t1.start();
} else { // 如果已启动,则关闭它并递。
do_close(); // 关闭了标志位,并不等于关上了生产线程,因为生产线程的第一次任务还没结束。
// 后面的递归等于一个线程启动两次,这是线程不允许的。
//try {Thread.sleep(2000);} catch (Exception e) {}// java.lang.IllegalThreadStateException
do_button_1_start();
}
}
class Computer {
private String name = "商品";
private int i = 0;
private Computer() {
}
private boolean flag = false;
public synchronized void sc() {
if (flag) {
try {super.wait();} catch (InterruptedException e) {}
}
try {
Thread.sleep(2000);
} catch (Exception e) {
}
;
this.name = "商品" + (++i);
text_1.setText("生产" + this.name + "\r\n");
this.flag = true;
super.notify();
}
public synchronized void xf() {
if (!flag) {
try {super.wait();} catch (InterruptedException e) {}// 消费及搬运时间5秒
}
try {
Thread.sleep(2000);
} catch (Exception e) {
}
text_1.setText(""); // 将产品搬走了
text_2.setText("消费" + this.name + "\r\n");
this.flag = false;
super.notify();
}
}
class Sc implements Runnable {
private Computer computer;
public Sc(Computer computer) {
this.computer = computer;
}
boolean isstart = false;// 线程启动标志
public void run() {
while (isstart) {
computer.sc();
}
}
}
class Xf implements Runnable {
private Computer computer;
public Xf(Computer computer) {
this.computer = computer;
}
boolean isstart = false;// 线程启动标志
public void run() {
while (isstart) {
computer.xf();
}
}
}
}
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2