黑马程序员技术交流社区

标题: 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
  1. package SwingThread;

  2. import java.awt.BorderLayout;
  3. import java.awt.Container;
  4. import java.awt.EventQueue;
  5. import java.awt.FlowLayout;
  6. import java.awt.GridLayout;
  7. import java.awt.event.ActionEvent;
  8. import java.awt.event.ActionListener;

  9. import javax.swing.JButton;
  10. import javax.swing.JFrame;
  11. import javax.swing.JLabel;
  12. import javax.swing.JPanel;
  13. import javax.swing.JScrollPane;
  14. import javax.swing.JSplitPane;
  15. import javax.swing.JTextArea;


  16. public class SwingThreadScXf extends JFrame {
  17.         // 主方法主要启动一个窗体
  18.         public static void main(String[] args) {
  19.                 EventQueue.invokeLater(new Runnable() {
  20.                         public void run() {
  21.                                 new SwingThreadScXf().setVisible(true);
  22.                         }
  23.                 });
  24.         }

  25.         // 下面这些组件因为要被线程访问,所以将它们作为成员变量,方便内部类调用。
  26.         private JTextArea text_1 = new JTextArea(30, 50);
  27.         private JTextArea text_2 = new JTextArea(30, 5);
  28.         private JButton button_1 = new JButton("开始生产");
  29.         private JButton button_2 = new JButton("开始消费");
  30.         private JButton button_3 = new JButton("停止所有线程");

  31.         // 构造方法用于生成窗体 以及各组件在窗体中的摆放位置。
  32.         public SwingThreadScXf() {
  33.                 super();
  34.                 setBounds(100, 100, 500, 300);
  35.                 setLayout(new BorderLayout());
  36.                 setTitle("在Swing中演示生产者与消费者线程实例");
  37.                 Container container = getContentPane();

  38.                 JScrollPane scroll_Pane = new JScrollPane(text_1);
  39.                 JScrollPane scrol2_Pane = new JScrollPane(text_2);
  40.                 JPanel panel_left = new JPanel(new GridLayout(2, 1, 0, 0));
  41.                 JPanel panel_right = new JPanel(new GridLayout(2, 1, 0, 0));
  42.                 panel_left.add(new JLabel("生产者线程"));
  43.                 panel_left.add(scroll_Pane);
  44.                 panel_right.add(new JLabel("消费者线程"));
  45.                 panel_right.add(scrol2_Pane);
  46.                 JSplitPane hsplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
  47.                                 panel_left, panel_right);
  48.                 hsplit.setDividerLocation(0.5); // 设置了分隔条所在的位置,为什么不成功呢?想要分隔条在分割面板的中间。

  49.                 container.add(hsplit, BorderLayout.CENTER);
  50.                 // 为按钮添加事件管理器
  51.                 button_1.addActionListener(new ActionListener() {
  52.                         public void actionPerformed(ActionEvent e) {
  53.                                 do_button_1_start();
  54.                         }
  55.                 });
  56.                 button_2.addActionListener(new ActionListener() {
  57.                         public void actionPerformed(ActionEvent e) {
  58.                                 do_button_2_start();
  59.                         }
  60.                 });
  61.                 button_3.addActionListener(new ActionListener() {
  62.                         public void actionPerformed(ActionEvent e) {
  63.                                 do_close();
  64.                         }
  65.                 });
  66.                 JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
  67.                 panel.add(button_1);
  68.                 panel.add(button_2);
  69.                 panel.add(button_3);
  70.                 container.add(panel, BorderLayout.SOUTH);

  71.         }

  72.         private Computer computer = new Computer();
  73.         private Xf xfz = new Xf(computer);
  74.         private Sc scz = new Sc(computer);
  75.         Thread t1 = new Thread(scz);
  76.         Thread t2 = new Thread(xfz);

  77.         protected void do_close() { // 关闭相应的启动线程,应等待到少执行一个循环。
  78.                 if (t1.isAlive()) {
  79.                         scz.isstart = false;
  80.                         /*if (!t1.interrupted()) { // 测试生产线程是否忆中断,若没中断则中断它。
  81.                                 t1.interrupt();
  82.                         }*/                //启动它会发生        java.lang.StackOverflowError
  83.                 }
  84.                 if (t1.isAlive()) {
  85.                         xfz.isstart = false;
  86.                         /*if (!t1.interrupted()) { // 测试消费线程是否忆中断,若没中断则中断它。
  87.                                 t1.interrupt();
  88.                         }*/
  89.                 }
  90.                 // 启用它会发生:java.lang.IllegalThreadStateException
  91.                 // try{Thread.sleep(2000);}catch(Exception e){}//等待线程到少执行了一次循环。

  92.         }

  93.         // 事件处理方法,启动线程或关闭线程
  94.         protected void do_button_2_start() {

  95.                 if (!t2.isAlive()) { // 判断线程是否启动,没启动的话启动。
  96.                         openflag(); // 每一次启动前都要对线程标启动的标记进行设置。
  97.                         t2.start();
  98.                 } else { // 如果已启动,则关闭它并递归。
  99.                         do_close();

  100.                         do_button_2_start();
  101.                 }
  102.         }

  103.         private void openflag() {// 重设线程启动的标记为可以启。
  104.                 scz.isstart = true;
  105.                 xfz.isstart = true;
  106.         }

  107.         protected void do_button_1_start() {

  108.                 if (!t1.isAlive()) {         // 判断线程是否启动,没启动的话启动。
  109.                         openflag();                 // 每一次启动前都要对线程标启记的标志进行设置。
  110.                         t1.start();
  111.                 } else {                                 // 如果已启动,则关闭它并递。
  112.                         do_close();                 // 关闭了标志位,并不等于关上了生产线程,因为生产线程的第一次任务还没结束。
  113.                                                                 // 后面的递归等于一个线程启动两次,这是线程不允许的。
  114.                         //try {Thread.sleep(2000);} catch (Exception e) {}// java.lang.IllegalThreadStateException
  115.                         do_button_1_start();
  116.                 }
  117.         }

  118.         class Computer {
  119.                 private String name = "商品";
  120.                 private int i = 0;

  121.                 private Computer() {
  122.                 }

  123.                 private boolean flag = false;

  124.                 public synchronized void sc() {

  125.                         if (flag) {
  126.                                 try {super.wait();} catch (InterruptedException e) {}
  127.                         }
  128.                         try {
  129.                                 Thread.sleep(2000);
  130.                         } catch (Exception e) {
  131.                         }
  132.                         ;
  133.                         this.name = "商品" + (++i);
  134.                         text_1.setText("生产" + this.name + "\r\n");
  135.                         this.flag = true;
  136.                         super.notify();

  137.                 }

  138.                 public synchronized void xf() {
  139.                         if (!flag) {
  140.                                 try {super.wait();} catch (InterruptedException e) {}// 消费及搬运时间5秒
  141.                         }
  142.                         try {
  143.                                 Thread.sleep(2000);
  144.                         } catch (Exception e) {
  145.                         }
  146.                         text_1.setText(""); // 将产品搬走了
  147.                         text_2.setText("消费" + this.name + "\r\n");
  148.                         this.flag = false;
  149.                         super.notify();
  150.                 }
  151.         }

  152.         class Sc implements Runnable {
  153.                 private Computer computer;

  154.                 public Sc(Computer computer) {
  155.                         this.computer = computer;
  156.                 }

  157.                 boolean isstart = false;// 线程启动标志

  158.                 public void run() {
  159.                         while (isstart) {

  160.                                 computer.sc();
  161.                         }
  162.                 }

  163.         }

  164.         class Xf implements Runnable {
  165.                 private Computer computer;

  166.                 public Xf(Computer computer) {
  167.                         this.computer = computer;
  168.                 }

  169.                 boolean isstart = false;// 线程启动标志

  170.                 public void run() {
  171.                         while (isstart) {

  172.                                 computer.xf();
  173.                         }
  174.                 }

  175.         }

  176. }
复制代码





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2