本帖最后由 施大勇 于 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();
- }
- }
- }
- }
复制代码 |
|