201772020113 李清华《面向对象程序设计(java)》第16周学习总结
1、实验目的与要求
(1) 掌握线程概念;
(2) 掌握线程创建的两种技术;
(3) 理解和掌握线程的优先级属性及调度方法;
(4) 掌握线程同步的概念及实现技术;
2、实验内容和步骤
实验1:测试程序并进行代码注释。
测试程序1:
l 在elipse IDE中调试运行ThreadTest,结合程序运行结果理解程序;
l 掌握线程概念;
l 掌握用Thread的扩展类实现线程的方法;
利用Runnable接口改造程序,掌握用Runnable接口创建线程的方法。
class Lefthand extends Thread { public void run() { for(int i=0;i<=5;i++) { System.out.println("You are Students!"); try{ sleep(500); } catch(InterruptedException e) { System.out.println("Lefthand error.");} } } } class Righthand extends Thread { public void run() { for(int i=0;i<=5;i++) { System.out.println("I am a Teacher!"); try{ sleep(300); } catch(InterruptedException e) { System.out.println("Righthand error.");} } } } public class ThreadTest { static Lefthand left; static Righthand right; public static void main(String[] args) { left=new Lefthand(); right=new Righthand(); left.start(); right.start(); } } |
运行结果:
测试程序2:
l 在Elipse环境下调试教材625页程序14-1、14-2 、14-3,结合程序运行结果理解程序;
1 package bounce; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 7 /** 8 * 显示动画弹跳球 9 * @version 1.34 2015-06-21 10 * @author Cay Horstmann 11 */ 12 public class Bounce 13 { 14 public static void main(String[] args) 15 { 16 EventQueue.invokeLater(() -> { 17 JFrame frame = new BounceFrame(); 18 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 19 frame.setVisible(true); 20 }); 21 } 22 } 23 24 /** 25 * 框架与球组件和按钮 26 */ 27 class BounceFrame extends JFrame 28 { 29 private BallComponent comp; 30 public static final int STEPS = 1000; 31 public static final int DELAY = 3; 32 33 /** 34 * 使用组件构造框架以显示弹跳球和“开始”和“关闭”按钮 35 */ 36 public BounceFrame() 37 { 38 setTitle("Bounce"); 39 comp = new BallComponent(); 40 add(comp, BorderLayout.CENTER); 41 JPanel buttonPanel = new JPanel(); 42 addButton(buttonPanel, "Start", event -> addBall()); 43 addButton(buttonPanel, "Close", event -> System.exit(0)); 44 add(buttonPanel, BorderLayout.SOUTH); 45 pack(); 46 } 47 48 /** 49 * 向容器添加按钮 50 * @param c the container 51 * @param title the button title 52 * @param listener the action listener for the button 53 */ 54 public void addButton(Container c, String title, ActionListener listener) 55 { 56 JButton button = new JButton(title); 57 c.add(button); 58 button.addActionListener(listener); 59 } 60 61 /** 62 * 在面板上添加一个弹跳球,使其反弹1,000次 63 */ 64 public void addBall() 65 { 66 try 67 { 68 Ball ball = new Ball(); 69 comp.add(ball); 70 71 for (int i = 1; i <= STEPS; i++) 72 { 73 ball.move(comp.getBounds()); 74 comp.paint(comp.getGraphics()); 75 Thread.sleep(DELAY); 76 } 77 } 78 catch (InterruptedException e) 79 { 80 } 81 } 82 }
1 package bounce; 2 3 import java.awt.*; 4 import java.util.*; 5 import javax.swing.*; 6 7 /** 8 * 绘制球的组件 9 * @version 1.34 2012-01-26 10 * @author Cay Horstmann 11 */ 12 public class BallComponent extends JPanel 13 { 14 private static final int DEFAULT_WIDTH = 450; 15 private static final int DEFAULT_HEIGHT = 350; 16 17 private java.util.List<Ball> balls = new ArrayList<>(); 18 19 /** 20 * 向组件添加球 21 * @param b the ball to add 22 */ 23 public void add(Ball b) 24 { 25 balls.add(b); 26 } 27 28 public void paintComponent(Graphics g) 29 { 30 super.paintComponent(g); // 擦除背景 31 Graphics2D g2 = (Graphics2D) g; 32 for (Ball b : balls) 33 { 34 g2.fill(b.getShape()); 35 } 36 } 37 38 public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } 39 }
1 package bounce; 2 3 import java.awt.geom.*; 4 5 /** 6 * 从矩形边缘移动并弹回的球 7 * @version 1.33 2007-05-17 8 * @author Cay Horstmann 9 */ 10 public class Ball 11 { 12 private static final int XSIZE = 15; 13 private static final int YSIZE = 15; 14 private double x = 0; 15 private double y = 0; 16 private double dx = 1; 17 private double dy = 1; 18 19 /** 20 * 将球移动到下一个位置,如果碰到其中一个边缘则反转方向 21 */ 22 public void move(Rectangle2D bounds) 23 { 24 x += dx; 25 y += dy; 26 if (x < bounds.getMinX()) 27 { 28 x = bounds.getMinX(); 29 dx = -dx; 30 } 31 if (x + XSIZE >= bounds.getMaxX()) 32 { 33 x = bounds.getMaxX() - XSIZE; 34 dx = -dx; 35 } 36 if (y < bounds.getMinY()) 37 { 38 y = bounds.getMinY(); 39 dy = -dy; 40 } 41 if (y + YSIZE >= bounds.getMaxY()) 42 { 43 y = bounds.getMaxY() - YSIZE; 44 dy = -dy; 45 } 46 } 47 48 /** 49 * 获取球在其当前位置的形状。 50 */ 51 public Ellipse2D getShape() 52 { 53 return new Ellipse2D.Double(x, y, XSIZE, YSIZE); 54 } 55 }
l 在Elipse环境下调试教材631页程序14-4,结合程序运行结果理解程序;
1 package bounceThread; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 6 import javax.swing.*; 7 8 /** 9 * 显示动画弹跳球 10 * @version 1.34 2015-06-21 11 * @author Cay Horstmann 12 */ 13 public class BounceThread 14 { 15 public static void main(String[] args) 16 { 17 EventQueue.invokeLater(() -> { 18 JFrame frame = new BounceFrame(); 19 frame.setTitle("BounceThread"); 20 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 21 frame.setVisible(true); 22 }); 23 } 24 } 25 26 /** 27 * 框架与球组件和按钮 28 */ 29 class BounceFrame extends JFrame 30 { 31 private BallComponent comp; 32 public static final int STEPS = 1000; 33 public static final int DELAY = 5; 34 35 36 /** 37 * 用显示弹跳球以及开始和关闭按钮的组件构建框架 38 */ 39 public BounceFrame() 40 { 41 comp = new BallComponent(); 42 add(comp, BorderLayout.CENTER); 43 JPanel buttonPanel = new JPanel(); 44 addButton(buttonPanel, "Start", event -> addBall()); 45 addButton(buttonPanel, "Close", event -> System.exit(0)); 46 add(buttonPanel, BorderLayout.SOUTH); 47 pack(); 48 } 49 50 /** 51 * 向容器添加按钮 52 * @param c the container 53 * @param title the button title 54 * @param listener the action listener for the button 55 */ 56 public void addButton(Container c, String title, ActionListener listener) 57 { 58 JButton button = new JButton(title); 59 c.add(button); 60 button.addActionListener(listener); 61 } 62 63 /** 64 * 在画布上添加一个弹跳球,并启动一个线程使其弹跳 65 */ 66 public void addBall() 67 { 68 Ball ball = new Ball(); 69 comp.add(ball); 70 Runnable r = () -> { 71 try 72 { 73 for (int i = 1; i <= STEPS; i++) 74 { 75 ball.move(comp.getBounds()); 76 comp.repaint(); 77 Thread.sleep(DELAY); 78 } 79 } 80 catch (InterruptedException e) 81 { 82 } 83 }; 84 Thread t = new Thread(r); 85 t.start(); 86 } 87 }
l 对比两个程序,理解线程的概念和用途;
l 掌握线程创建的两种技术。
测试程序3:分析以下程序运行结果并理解程序。
class Race extends Thread { public static void main(String args[]) { Race[] runner=new Race[4]; for(int i=0;i<4;i++) runner[i]=new Race( ); for(int i=0;i<4;i++) runner[i].start( ); runner[1].setPriority(MIN_PRIORITY); runner[3].setPriority(MAX_PRIORITY);} public void run( ) { for(int i=0; i<1000000; i++); System.out.println(getName()+"线程的优先级是"+getPriority()+"已计算完毕!"); } } |
1 class Race extends Thread { 2 public static void main(String args[]) { 3 Race[] runner = new Race[4]; 4 for (int i = 0; i < 4; i++) 5 runner[i] = new Race(); 6 for (int i = 0; i < 4; i++) 7 runner[i].start(); 8 runner[1].setPriority(MIN_PRIORITY);// 更改线程为最低优先级 9 runner[3].setPriority(MAX_PRIORITY);// 更改线程为最高优先级 10 } 11 12 public void run() { 13 for (int i = 0; i < 1000000; i++);// 起延时作用 14 System.out.println(getName() + "线程的优先级是" + getPriority() + "已计算完毕!"); 15 } 16 }
测试程序4
l 教材642页程序模拟一个有若干账户的银行,随机地生成在这些账户之间转移钱款的交易。每一个账户有一个线程。在每一笔交易中,会从线程所服务的账户中随机转移一定数目的钱款到另一个随机账户。
l 在Elipse环境下调试教材642页程序14-5、14-6,结合程序运行结果理解程序;
1 package unsynch; 2 3 import java.util.*; 4 5 /** 6 * 有许多银行账户的银行 7 * @version 1.30 2004-08-01 8 * @author Cay Horstmann 9 */ 10 public class Bank 11 { 12 private final double[] accounts; 13 14 /** 15 * 建设银行 . 16 * @param 账号的数目n 17 * @param 每个账户的初始余额 18 */ 19 public Bank(int n, double initialBalance) 20 { 21 accounts = new double[n]; 22 Arrays.fill(accounts, initialBalance); 23 } 24 25 /** 26 * 把钱从一个账户转到另一个账户。 27 * @param 从账户转账 28 * @param 转到要转账的账户 29 * @param 转账金额 30 */ 31 public void transfer(int from, int to, double amount) 32 { 33 if (accounts[from] < amount) return; 34 System.out.print(Thread.currentThread()); 35 accounts[from] -= amount; 36 System.out.printf(" %10.2f from %d to %d", amount, from, to); 37 accounts[to] += amount; 38 System.out.printf(" Total Balance: %10.2f%n", getTotalBalance()); 39 } 40 41 /** 42 * 获取所有帐户余额的总和。 43 * @return 总余额 44 */ 45 public double getTotalBalance() 46 { 47 double sum = 0; 48 49 for (double a : accounts) 50 sum += a; 51 52 return sum; 53 } 54 55 /** 56 * 获取银行中的帐户数量。 57 * @return 账户数量 58 */ 59 public int size() 60 { 61 return accounts.length; 62 } 63 }
1 package unsynch; 2 3 /** 4 * 当多个线程访问数据结构时,此程序显示数据损坏 5 * @version 1.31 2015-06-21 6 * @author Cay Horstmann 7 */ 8 public class UnsynchBankTest 9 { 10 public static final int NACCOUNTS = 100; 11 public static final double INITIAL_BALANCE = 1000; 12 public static final double MAX_AMOUNT = 1000; 13 public static final int DELAY = 10; 14 15 public static void main(String[] args) 16 { 17 Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE); 18 for (int i = 0; i < NACCOUNTS; i++) 19 { 20 int fromAccount = i; 21 Runnable r = () -> { 22 try 23 { 24 while (true) 25 { 26 int toAccount = (int) (bank.size() * Math.random()); 27 double amount = MAX_AMOUNT * Math.random(); 28 bank.transfer(fromAccount, toAccount, amount); 29 Thread.sleep((int) (DELAY * Math.random())); 30 } 31 } 32 catch (InterruptedException e) 33 { 34 } 35 }; 36 Thread t = new Thread(r); 37 t.start(); 38 } 39 } 40 }
综合编程练习
编程练习1
1. 设计一个用户信息采集程序,要求如下:
(1)用户信息输入界面如下图所示:
(2)用户点击提交按钮时,用户输入信息显示控制台界面
(3)用户点击重置按钮后,清空用户已输入信息
(4)点击窗口关闭,程序退出。
1 package xxcj; 2 import java.awt.EventQueue; 3 4 import javax.swing.JFrame; 5 6 public class Main { 7 public static void main(String[] args) { 8 EventQueue.invokeLater(() -> { 9 DemoJFrame page = new DemoJFrame(); 10 }); 11 } 12 }
1 package xxcj; 2 import java.awt.Dimension; 3 import java.awt.Toolkit; 4 import java.awt.Window; 5 6 public class WinCenter { 7 public static void center(Window win){ 8 Toolkit tkit = Toolkit.getDefaultToolkit(); 9 Dimension sSize = tkit.getScreenSize(); 10 Dimension wSize = win.getSize(); 11 if(wSize.height > sSize.height){ 12 wSize.height = sSize.height; 13 } 14 if(wSize.width > sSize.width){ 15 wSize.width = sSize.width; 16 } 17 win.setLocation((sSize.width - wSize.width)/ 2, (sSize.height - wSize.height)/ 2); 18 } 19 }
1 package xxcj; 2 3 import java.awt.Dimension; 4 import java.awt.FlowLayout; 5 import java.awt.GridLayout; 6 7 import javax.swing.BorderFactory; 8 import javax.swing.ButtonGroup; 9 import javax.swing.JButton; 10 import javax.swing.JCheckBox; 11 import javax.swing.JComboBox; 12 import javax.swing.JFrame; 13 import javax.swing.JLabel; 14 import javax.swing.JPanel; 15 import javax.swing.JRadioButton; 16 import javax.swing.JTextField; 17 18 public class DemoJFrame extends JFrame { 19 private JPanel jPanel1; 20 private JPanel jPanel2; 21 private JPanel jPanel3; 22 private JPanel jPanel4; 23 private JTextField fieldname; 24 private JComboBox comboBox; 25 private JTextField fieldadress; 26 private ButtonGroup bg; 27 private JRadioButton nan; 28 private JRadioButton nv; 29 private JCheckBox sing; 30 private JCheckBox dance; 31 private JCheckBox draw; 32 33 public DemoJFrame() { 34 this.setSize(400, 300); 35 this.setVisible(true); 36 this.setTitle("编程练习一"); 37 this.setDefaultCloseOperation(EXIT_ON_CLOSE); 38 WinCenter.center(this); 39 jPanel1 = new JPanel(); 40 setJPanel1(jPanel1); 41 jPanel2 = new JPanel(); 42 setJPanel2(jPanel2); 43 jPanel3 = new JPanel(); 44 setJPanel3(jPanel3); 45 jPanel4 = new JPanel(); 46 setJPanel4(jPanel4); 47 FlowLayout flowLayout = new FlowLayout(); 48 this.setLayout(flowLayout); 49 this.add(jPanel1); 50 this.add(jPanel2); 51 this.add(jPanel3); 52 this.add(jPanel4); 53 54 } 55 56 private void setJPanel1(JPanel jPanel) { 57 jPanel.setPreferredSize(new Dimension(300, 50)); 58 jPanel.setLayout(new GridLayout(1, 4)); 59 JLabel name = new JLabel(" 姓名:"); 60 fieldname = new JTextField(""); 61 JLabel study = new JLabel(" 学历:"); 62 comboBox = new JComboBox(); 63 comboBox.addItem("初中"); 64 comboBox.addItem("高中"); 65 comboBox.addItem("本科"); 66 jPanel.add(name); 67 jPanel.add(fieldname); 68 jPanel.add(study); 69 jPanel.add(comboBox); 70 71 } 72 73 private void setJPanel2(JPanel jPanel) { 74 jPanel.setPreferredSize(new Dimension(300, 50)); 75 jPanel.setLayout(new GridLayout(1, 4)); 76 JLabel name = new JLabel(" 地址:"); 77 fieldadress = new JTextField(); 78 JLabel study = new JLabel(" 爱好:"); 79 JPanel selectBox = new JPanel(); 80 selectBox.setLayout(new GridLayout(3, 1)); 81 sing = new JCheckBox("唱歌"); 82 dance = new JCheckBox("跳舞"); 83 draw = new JCheckBox("画画"); 84 selectBox.add(sing); 85 selectBox.add(dance); 86 selectBox.add(draw); 87 jPanel.add(name); 88 jPanel.add(fieldadress); 89 jPanel.add(study); 90 jPanel.add(selectBox); 91 } 92 93 private void setJPanel3(JPanel jPanel) { 94 jPanel.setPreferredSize(new Dimension(300,70)); 95 JLabel sex = new JLabel(" 性别:"); 96 JPanel selectBox = new JPanel(); 97 selectBox.setLayout(new GridLayout(2,1)); 98 bg = new ButtonGroup(); 99 nan = new JRadioButton("男"); 100 nv = new JRadioButton("女"); 101 bg.add(nan); 102 bg.add(nv); 103 selectBox.add(nan); 104 selectBox.add(nv); 105 jPanel.add(sex); 106 jPanel.add(selectBox); 107 108 } 109 110 private void setJPanel4(JPanel jPanel) { 111 jPanel.setPreferredSize(new Dimension(300, 150)); 112 FlowLayout flowLayout = new FlowLayout(FlowLayout.CENTER, 50, 10); 113 jPanel.setLayout(flowLayout); 114 jPanel.setLayout(flowLayout); 115 JButton sublite = new JButton("提交"); 116 JButton reset = new JButton("重置"); 117 sublite.addActionListener((e) -> valiData()); 118 reset.addActionListener((e) -> Reset()); 119 jPanel.add(sublite); 120 jPanel.add(reset); 121 } 122 123 private void valiData() { 124 String name = fieldname.getText().toString().trim(); 125 String xueli = comboBox.getSelectedItem().toString().trim(); 126 String address = fieldadress.getText().toString().trim(); 127 System.out.println(name); 128 System.out.println(xueli); 129 String hobbystring=""; 130 if (sing.isSelected()) { 131 hobbystring+="唱歌"; 132 } 133 if (dance.isSelected()) { 134 hobbystring+="跳舞"; 135 } 136 if (draw.isSelected()) { 137 hobbystring+="画画"; 138 } 139 System.out.println(address); 140 if (nan.isSelected()) { 141 System.out.println("男"); 142 } 143 if (nv.isSelected()) { 144 System.out.println("女"); 145 } 146 System.out.println(hobbystring); 147 } 148 149 private void Reset() { 150 fieldadress.setText(null); 151 fieldname.setText(null); 152 comboBox.setSelectedIndex(0); 153 sing.setSelected(false); 154 dance.setSelected(false); 155 draw.setSelected(false); 156 bg.clearSelection(); 157 } 158 }
2.创建两个线程,每个线程按顺序输出5次“你好”,每个“你好”要标明来自哪个线程及其顺序号。
1 package nihao; 2 3 class Lefthand extends Thread { 4 public void run() { 5 for (int i = 0; i < 5; i++) { 6 System.out.println(i + 1 + ":a.你好!"); 7 try { 8 Thread.sleep(500); 9 } catch (InterruptedException e) { 10 System.out.println("Lefthand error."); 11 } 12 } 13 } 14 } 15 16 class Righthand extends Thread { 17 public void run() { 18 for (int i = 0; i < 5; i++) { 19 System.out.println(i + 1 + ":b.你好!"); 20 try { 21 Thread.sleep(300); 22 } catch (InterruptedException e) { 23 System.out.println("Righthand error."); 24 } 25 } 26 } 27 } 28 29 public class ThreadTest { 30 static Lefthand left; 31 static Righthand right; 32 public static void main(String[] args) { 33 left = new Lefthand(); 34 right = new Righthand(); 35 left.start(); 36 right.start(); 37 } 38 }
3. 完善实验十五 GUI综合编程练习程序。