1、实验目的与要求
(1) 掌握线程概念;
(2) 掌握线程创建的两种技术;
(3) 理解和掌握线程的优先级属性及调度方法;
(4) 掌握线程同步的概念及实现技术;
2、实验内容和步骤
实验1:测试程序并进行代码注释。
测试程序1:
l 在elipse IDE中调试运行ThreadTest,结合程序运行结果理解程序;
l 掌握线程概念;
l 掌握用Thread的扩展类实现线程的方法;
l 利用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(); } }
package ll; class Lefthand implements Runnable { public void run() { for(int i=0;i<=5;i++) { System.out.println("You are Students!"); try{ Thread. sleep(500); } catch(InterruptedException e) { System.out.println("Lefthand error.");} } } } class Righthand implements Runnable { public void run() { for(int i=0;i<=5;i++) { System.out.println("I am a Teacher!"); try{ Thread. sleep(300); } catch(InterruptedException e) { System.out.println("Righthand error.");} } } } public class ThreadTest { public static void main(String[] args) //throws InterruptedException { Runnable A=new Lefthand(); Thread t=new Thread(A); Runnable B=new Righthand (); Thread h=new Thread(B); t.start(); h.start(); /*System.out.println("Righthand error."); Thread. sleep(3000); System.out.println("Righthand error.");*/ } }
测试程序2:
l 在Elipse环境下调试教材625页程序14-1、14-2 、14-3,结合程序运行结果理解程序;
l 在Elipse环境下调试教材631页程序14-4,结合程序运行结果理解程序;
l 对比两个程序,理解线程的概念和用途;
l 掌握线程创建的两种技术。
14-1
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Bounce { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new BounceFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } /** * The frame with ball component and buttons. */ class BounceFrame extends JFrame { private BallComponent comp; public static final int STEPS = 1000; public static final int DELAY = 3; /** * 用显示弹跳球和的组件构造框架 * 启动和关闭按钮 */ public BounceFrame() { setTitle("Bounce"); comp = new BallComponent(); add(comp, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(); addButton(buttonPanel, "Start", event -> addBall()); addButton(buttonPanel, "Close", event -> System.exit(0)); add(buttonPanel, BorderLayout.SOUTH); pack(); } /** * 将按钮添加到容器中。 * @param c 容器 * @param 按钮标题 * @param 侦听器按钮的操作侦听器 */ public void addButton(Container c, String title, ActionListener listener) { JButton button = new JButton(title); c.add(button); button.addActionListener(listener); } /** * 向面板中添加一个弹跳球,使其弹跳1000次。 */ public void addBall() { try { Ball ball = new Ball(); comp.add(ball); for (int i = 1; i <= STEPS; i++) { ball.move(comp.getBounds()); comp.paint(comp.getGraphics()); Thread.sleep(DELAY); } } catch (InterruptedException e) { } } }
import java.awt.*; import java.util.*; import javax.swing.*; /** * 画球的部件。 */ public class BallComponent extends JPanel { private static final int DEFAULT_WIDTH = 450; private static final int DEFAULT_HEIGHT = 350; private java.util.List<Ball> balls = new ArrayList<>(); /** * 向组件添加一个球。 */ public void add(Ball b) { balls.add(b); } public void paintComponent(Graphics g) { super.paintComponent(g); // erase background Graphics2D g2 = (Graphics2D) g; for (Ball b : balls) { g2.fill(b.getShape()); } } public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } }
import java.awt.geom.*; /** * 从长方形边缘上移动和弹跳的球 */ public class Ball { private static final int XSIZE = 15; private static final int YSIZE = 15; private double x = 0; private double y = 0; private double dx = 1; private double dy = 1; /** * 将球移动到下一个位置,如果球碰到其中一条边,则反向移动 */ public void move(Rectangle2D bounds) { x += dx; y += dy; if (x < bounds.getMinX()) { x = bounds.getMinX(); dx = -dx; } if (x + XSIZE >= bounds.getMaxX()) { x = bounds.getMaxX() - XSIZE; dx = -dx; } if (y < bounds.getMinY()) { y = bounds.getMinY(); dy = -dy; } if (y + YSIZE >= bounds.getMaxY()) { y = bounds.getMaxY() - YSIZE; dy = -dy; } } /** * 获取球在当前位置的形状。 */ public Ellipse2D getShape() { return new Ellipse2D.Double(x, y, XSIZE, YSIZE); } }
14-4
import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * 显示动画弹跳球。 */ public class BounceThread { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new BounceFrame(); frame.setTitle("BounceThread"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } /** * 带有面板和按钮的框架。 */ class BounceFrame extends JFrame { private BallComponent comp; public static final int STEPS = 1000; public static final int DELAY = 5; /** * 用显示弹跳球和的组件构造框架 * 启动和关闭按钮 */ public BounceFrame() { comp = new BallComponent(); add(comp, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(); addButton(buttonPanel, "Start", event -> addBall()); addButton(buttonPanel, "Close", event -> System.exit(0)); add(buttonPanel, BorderLayout.SOUTH); pack(); } /** * 将按钮添加到容器中。 * @param c the container * @param title the button title * @param listener the action listener for the button */ public void addButton(Container c, String title, ActionListener listener) { JButton button = new JButton(title); c.add(button); button.addActionListener(listener); } /** * 在画布上添加一个弹跳球,并启动一根线使其弹跳 */ public void addBall() { Ball ball = new Ball(); comp.add(ball); Runnable r = () -> { try { for (int i = 1; i <= STEPS; i++) { ball.move(comp.getBounds()); comp.repaint(); Thread.sleep(DELAY); } } catch (InterruptedException e) { } }; Thread t = new Thread(r); t.start(); } }
public class BallComponent extends JPanel
public class Ball
测试程序3:分析以下程序运行结果并理解程序。
package 线程; 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()+"已计算完毕!"); } }
测试程序4
l 教材642页程序模拟一个有若干账户的银行,随机地生成在这些账户之间转移钱款的交易。每一个账户有一个线程。在每一笔交易中,会从线程所服务的账户中随机转移一定数目的钱款到另一个随机账户。
l 在Elipse环境下调试教材642页程序14-5、14-6,结合程序运行结果理解程序;
public class UnsynchBankTest { public static final int NACCOUNTS = 100; public static final double INITIAL_BALANCE = 1000; public static final double MAX_AMOUNT = 1000; public static final int DELAY = 10; public static void main(String[] args) { Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE); for (int i = 0; i < NACCOUNTS; i++) { int fromAccount = i; Runnable r = () -> { try { while (true) { int toAccount = (int) (bank.size() * Math.random()); double amount = MAX_AMOUNT * Math.random(); bank.transfer(fromAccount, toAccount, amount); Thread.sleep((int) (DELAY * Math.random())); } } catch (InterruptedException e) { } }; Thread t = new Thread(r); t.start(); } } }
import java.util.*; public class Bank { private final double[] accounts; /** * Constructs the bank. * @param n the number of accounts * @param initialBalance the initial balance for each account */ public Bank(int n, double initialBalance) { accounts = new double[n]; Arrays.fill(accounts, initialBalance); } /** * Transfers money from one account to another. * @param from the account to transfer from * @param to the account to transfer to * @param amount the amount to transfer */ public void transfer(int from, int to, double amount) { if (accounts[from] < amount) return; System.out.print(Thread.currentThread()); accounts[from] -= amount; System.out.printf(" %10.2f from %d to %d", amount, from, to); accounts[to] += amount; System.out.printf(" Total Balance: %10.2f%n", getTotalBalance()); } /** * Gets the sum of all account balances. * @return the total balance */ public double getTotalBalance() { double sum = 0; for (double a : accounts) sum += a; return sum; } /** * Gets the number of accounts in the bank. * @return the number of accounts */ public int size() { return accounts.length; } }
合编程练习
编程练习1
- 设计一个用户信息采集程序,要求如下:
(1) 用户信息输入界面如下图所示:
(1) 用户点击提交按钮时,用户输入信息显示控制台界面;
(2) 用户点击重置按钮后,清空用户已输入信息;
{3}点击窗口关闭,程序退出。
package wzc; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JTextArea; public class w { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new FrameTest(); frame.setTitle("王志成"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } class FrameTest extends JFrame { private JPanel panel; private JRadioButton JRadioButton1,JRadioButton2; private ButtonGroup ButtonGroup; private JLabel JLabel; private JTextArea text1,text2; private JCheckBox h1,h2,h3; private JComboBox<String> JComboBox; private JButton Button1,Button2; public FrameTest() { setSize(700,500); panel=new JPanel(); panel.setLayout(null); ButtonGroup=new ButtonGroup(); JRadioButton1=new JRadioButton("男",false); JRadioButton1.setBounds(130,330, 80, 50); JRadioButton2=new JRadioButton("女",false); JRadioButton2.setBounds(130,300, 80,50); ButtonGroup.add(JRadioButton1); ButtonGroup.add(JRadioButton2); addJLabel("性别:",100,300); addJLabel("姓名:",100,50); addJLabel("地址:",90,150); addJLabel("资格:",400,50); addJLabel("喜好:",400,150); text1=new JTextArea(1,1);text1.setBounds(150,70, 120, 30);text1.setLineWrap(true); text2=new JTextArea(5,3);text2.setBounds(150,160, 130, 100);text2.setLineWrap(true); h1=new JCheckBox("读书");h1.setBounds(450,160,100,30); h2=new JCheckBox("跳舞");h2.setBounds(450,180,100,30); h3=new JCheckBox("唱歌");h3.setBounds(450,200,100,30); JComboBox=new JComboBox<>(); JComboBox.addItem("研究生"); JComboBox.addItem("本科生"); JComboBox.addItem("专科生"); JComboBox.setBounds(500,65, 100, 20); Button1 = new JButton("提交");Button1.setBounds(200, 400, 100, 35); Button2 = new JButton("重置");Button2.setBounds(400, 400, 100, 35); Button1.addActionListener(new Action1()); Button2.addActionListener(new Action2()); panel.add(Button2); panel.add(Button1); panel.add(JComboBox); panel.add(h1); panel.add(h2); panel.add(h3); panel.add(text1); panel.add(text2); panel.add(JRadioButton1); panel.add(JRadioButton2); add(panel); } public void addJLabel(String n,int a,int b) { JLabel = new JLabel(n); JLabel.setBounds(a,b,100,50); panel.add(JLabel); } private class Action1 implements ActionListener { public void actionPerformed(ActionEvent event) { System.out.println("name:"+text1.getText()+" "+"address:"+text2.getText()); System.out.println("Qualification:"+JComboBox.getSelectedItem()); System.out.println("Hobby:"); if(h1.isSelected()==true)System.out.print(h1.getText()); if(h2.isSelected()==true)System.out.print(h2.getText()); if(h3.isSelected()==true)System.out.print(h3.getText()); System.out.println(" "+"sex:"); if(JRadioButton1.isSelected()==true)System.out.println(JRadioButton1.getText()); if(JRadioButton2.isSelected()==true)System.out.println(JRadioButton2.getText()); System.out.println(" "); } } private class Action2 implements ActionListener { public void actionPerformed(ActionEvent event) { text1.setText(null); text2.setText(null); h1.setSelected(false); h2.setSelected(false); h3.setSelected(false); ButtonGroup.clearSelection(); JComboBox.setSelectedIndex(0); } } }
2.创建两个线程,每个线程按顺序输出5次“你好”,每个“你好”要标明来自哪个线程及其顺序号。
package 线程; class Lefthand implements Runnable { public void run() { for(int i=1;i<=5;i++) { System.out.println(" Lefthand "+i+" 你好"); try{ Thread.sleep(1000); } catch(InterruptedException e) { System.out.println("Lefthand error.");} } } } class Righthand extends Thread { public void run() { for(int i=1;i<=5;i++) { System.out.println(" Righthand"+i+" 你好"); try{ sleep(300); } catch(InterruptedException e) { System.out.println("Righthand error.");} } } } public class xiancheng { static Righthand right; public static void main(String[] args) { right=new Righthand(); Runnable r=new Lefthand(); Thread t=new Thread(r); right.start(); t.start(); } }
3. 完善实验十五 GUI综合编程练习程序。
总结:这周学习了线程的相关知识,Java实现多线程有两种途径:‐创建Thread类的子类,-在程序中定义实现Runnable接口的类。又编写了一个用户界面的程序,使得对图形用户界面更加熟悉,