实验十六 线程技术
实验时间 2017-12-8
1、实验目的与要求
(1) 掌握线程概念;
多线程是进程执行过程中产生的多条执行线索,线程是比进程执行更小的单位。
线程不能独立存在,必须存在于进程中,同一进程的各线程间共享进程空间的数据。
每个线程有它自身的产生、存在和消亡的过程,是一个动态的概念。
多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行。
线程创建、销毁和切换的负荷远小于进程,又称为轻量级进程。
(2) 掌握线程创建的两种技术;
①创建Thread类的子类
首先须从Thread类派生出一个子类,在该子类中重写run方法。
例:
class hand extends Thread
{
public void run()
{……}
}
然后创建该子类的对象
Lefthand left = new Lefthand();
Righthand left = new Righthand();
最后用start()方法启动线程
left.start();
Right.start();
②在程序中定义实现Runnable接口的类
首先设计一个实现Runnable接口的类;
然后在类中根据需要重写run方法;
在创建该类对象,以此对象为参数建立Thread类的对象;
(3) 理解和掌握线程的优先级属性及调度方法;
Java的线程调度采用优先级策略:
优先级高的先执行,优先级低的后执行;
多线程系统会自动为每个线程分配一个优先级,缺省时,继承其父类的优先级;
任务紧急的优先级,其优先级较高;
同优先级的线程按照“先进先出”的队列原则;
(4) 掌握线程同步的概念及实现技术;
多线程并发运行不确定问题的解决方案:引入线程同步机制,使得另一线程要使用该方法,就只能等待。
在Java中解决多线程同步问题的方法有两种:
解决方案一:用ReentratLock保护代码块的基本结构如下:
myLock.lock();
try{
critical section
}
finally{
myLock.unlock();
}
有关锁对象和条件对象的关键要点:
锁用来保护代码片段,只要保证任何时刻只能有一个线程被保护的代码。
锁管理试图进入被保护代码段的进程。
锁可拥有一个或多个相关条件对象。
每个条件对象管理那些已经进入被保护的代码段但是还不能运行的线程。
解决方案二:synchronized关键字
synchronized关键字关键字作用:
某个类内方法用synchronized修饰后,该方法被称为同步方法;
只要某个线程正在访问同步方法,其他线程欲要访问同步方法就被阻塞,直至线程从同步方法返回前唤醒被阻塞线程,其他线程方法可进入同步方法。
一个线程在使用同步方法的中时,可能根据问题的需要,必须使用wait()方法使用本线程等待,暂时让出CPU的使用权,并允许其他线程使用这个同步方法。
线程如果用完同步方法,应当执行notifyAll()方法通知所有使用这个同步方法而处于等待的县城结束等待。
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(); } } |
改为用Runnable接口创建线程的方法。
package 小陈; 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 { static Thread left; static Thread right; public static void main(String[] args) { Runnable lefthand = new Lefthand(); left=new Thread(lefthand); left.start(); Runnable righthand = new Righthand(); right=new Thread(righthand); right.start(); } }
运行结果:
测试程序2:
l 在Elipse环境下调试教材625页程序14-1、14-2 、14-3,结合程序运行结果理解程序;
l 在Elipse环境下调试教材631页程序14-4,结合程序运行结果理解程序;
l 对比两个程序,理解线程的概念和用途;
l 掌握线程创建的两种技术。
package bounce; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * 显示一个动态弹跳球。 * @version 1.34 2015-06-21 * @author Cay Horstmann */ public class Bounce { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new BounceFrame(); 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 = 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());//调用getGraphics()方法绘制图形 Thread.sleep(DELAY); } } catch (InterruptedException e) { } } }
package bounce; import java.awt.*; import java.util.*; import javax.swing.*; /** * 画球的部件。 * @version 1.34 2012-01-26 * @author Cay Horstmann */ 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); // 擦除背景 Graphics2D g2 = (Graphics2D) g; for (Ball b : balls) { g2.fill(b.getShape()); } } public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } }
package bounce; import java.awt.geom.*; /** * 从长方形边缘上移动和弹跳的球 * @version 1.33 2007-05-17 * @author Cay Horstmann */ 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); } }
运行结果:
缺陷:Close按键没有作用,无法通过用户使程序停止。耗时。
package bounceThread; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * 显示动画弹跳球。 * @version 1.34 2015-06-21 * @author Cay Horstmann */ 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容器 * @param 按钮标题 * @param 侦听器按钮的操作侦听器 */ 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 = () -> { //相比于上一个程序代码,将任务代码移到实现了Runnable接口的类的run方法中。 //即将弹跳球代码放在一个独立的线程中 //由于Runnable是一个函数式接口,可以使用lambda表达式建立一个实例 try { for (int i = 1; i <= STEPS; i++) { ball.move(comp.getBounds()); comp.repaint(); //repaint()方法用于重绘组建,是一个具有刷新页面效果的方法 Thread.sleep(DELAY); //调用Thread.sleep()方法不会创建一个新线程,sleep是Thread类的静态方法,用于暂停当前线程的活动。 } } catch (InterruptedException e) //当发生此异常时,run方法将结束执行 { } }; Thread t = new Thread(r);//创建一个Thread对象。 t.start();//启动线程 } }
package bounceThread; import java.awt.*; import java.util.*; import javax.swing.*; /** * 画球的部件。 * @version 1.34 2012-01-26 * @author Cay Horstmann */ public class BallComponent extends JComponent { private static final int DEFAULT_WIDTH = 450; private static final int DEFAULT_HEIGHT = 350; private java.util.List<Ball> balls = new ArrayList<>(); /** * 向面板中添加一个球。 * @param b the ball to add */ public void add(Ball b) { balls.add(b); } public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; for (Ball b : balls) { g2.fill(b.getShape()); } } public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } }
package bounceThread; import java.awt.geom.*; /** 球从A的边缘上移动和反弹的球矩形 * @version 1.33 2007-05-17 * @author Cay Horstmann */ 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; /** Moves the ball to the next position, reversing direction if it hits one of the edges */ 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); } }
运行结果:
修正:通过运行一个线程中的关键代码来保护用户对程序的控制权。Close按键可以使用。
测试程序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()+"已计算完毕!"); } } |
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++);// for循环执行空语句,起延时作用 System.out.println(getName() + "线程的优先级是" + getPriority() + "已计算完毕!"); } }
运行结果:
测试程序4
l 教材642页程序模拟一个有若干账户的银行,随机地生成在这些账户之间转移钱款的交易。每一个账户有一个线程。在每一笔交易中,会从线程所服务的账户中随机转移一定数目的钱款到另一个随机账户。
l 在Elipse环境下调试教材642页程序14-5、14-6,结合程序运行结果理解程序;
package unsynch; /** * 当多个线程访问一个数据结构时,这个程序显示数据损坏。 * @version 1.31 2015-06-21 * @author Cay Horstmann */ 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(); } } }
package unsynch; import java.util.*; /** * 有许多银行账户的银行。 * @version 1.30 2004-08-01 * @author Cay Horstmann */ public class Bank { private final double[] accounts; /** *构建了银行。 * @param n账户数量 * @param 每个帐户的初始余额 */ public Bank(int n, double initialBalance) { accounts = new double[n]; Arrays.fill(accounts, initialBalance); } /** * 把钱从一个账户转到另一个账户。 */ 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()); } /** * 获取所有帐户余额的总和。 * @return 总平衡 */ public double getTotalBalance() { double sum = 0; for (double a : accounts) sum += a; return sum; } /** * 获取银行中的帐户编号。 * @return 账户数量 */ public int size() { return accounts.length; } }
运行结果:
综合编程练习
编程练习1
- 设计一个用户信息采集程序,要求如下:
(1) 用户信息输入界面如下图所示:
(2) 用户点击提交按钮时,用户输入信息显示控制台界面;
(3) 用户点击重置按钮后,清空用户已输入信息;
(4) 点击窗口关闭,程序退出。
package bounceThread; import java.awt.EventQueue; import javax.swing.JFrame; public class Mian { public static void main(String[] args) { EventQueue.invokeLater(() -> { DemoJFrame page = new DemoJFrame(); page.setTitle("用户信息录入框");// 设置标题 page.setSize(800, 400);// 设置窗口大小 page.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭操作 page.setVisible(true);//设置可见性 }); } }
package bounceThread; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.LayoutManager; import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Timer; import java.util.TimerTask; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.ButtonModel; 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.JTextField; public class DemoJFrame extends JFrame { private JPanel jPanel1; private JPanel jPanel2; private JPanel jPanel3; private JPanel jPanel4; private JTextField fieldname; private JComboBox comboBox; private JTextField fieldadress; private ButtonGroup bg; private JRadioButton man; private JRadioButton woman; private JCheckBox sing; private JCheckBox dance; private JCheckBox draw; public DemoJFrame() { //设置窗口居中 WinCenter.center(this); // 创建四个面板对象 jPanel1 = new JPanel(); setJPanel1(jPanel1); jPanel2 = new JPanel(); setJPanel2(jPanel2); jPanel3 = new JPanel(); setJPanel3(jPanel3); jPanel4 = new JPanel(); setJPanel4(jPanel4); // 设置容器的为流布局 FlowLayout flowLayout = new FlowLayout(); this.setLayout(flowLayout); // 将四个面板添加到容器中 this.add(jPanel1); this.add(jPanel2); this.add(jPanel3); this.add(jPanel4); } /* * 设置面一 */ private void setJPanel1(JPanel jPanel) { jPanel.setPreferredSize(new Dimension(700, 45)); // 给面板的布局设置为网格布局 一行4列 jPanel.setLayout(new GridLayout(1, 4)); JLabel name = new JLabel("姓名:"); name.setSize(100, 50); fieldname = new JTextField(""); fieldname.setSize(80, 20); JLabel study = new JLabel("学历:"); comboBox = new JComboBox(); comboBox.addItem("初中"); comboBox.addItem("高中"); comboBox.addItem("本科"); jPanel.add(name); jPanel.add(fieldname); jPanel.add(study); jPanel.add(comboBox); } /* * 设置面板二 */ private void setJPanel2(JPanel jPanel) { jPanel.setPreferredSize(new Dimension(700, 50)); // 给面板的布局设置为网格布局 一行4列 jPanel.setLayout(new GridLayout(1, 4)); JLabel name = new JLabel("地址:"); fieldadress = new JTextField(); fieldadress.setPreferredSize(new Dimension(150, 50)); JLabel study = new JLabel("爱好:"); JPanel selectBox = new JPanel(); selectBox.setBorder(BorderFactory.createTitledBorder("")); selectBox.setLayout(new GridLayout(3, 1)); sing = new JCheckBox("唱歌"); dance = new JCheckBox("跳舞"); draw = new JCheckBox("画画"); selectBox.add(sing); selectBox.add(dance); selectBox.add(draw); jPanel.add(name); jPanel.add(fieldadress); jPanel.add(study); jPanel.add(selectBox); } /* * 设置面板三 */ private void setJPanel3(JPanel jPanel) { jPanel.setPreferredSize(new Dimension(700, 150)); FlowLayout flowLayout = new FlowLayout(FlowLayout.LEFT); jPanel.setLayout(flowLayout); JLabel sex = new JLabel("性别:"); JPanel selectBox = new JPanel(); selectBox.setBorder(BorderFactory.createTitledBorder("")); selectBox.setLayout(new GridLayout(2, 1)); bg = new ButtonGroup(); man = new JRadioButton("男"); woman = new JRadioButton("女"); bg.add(man); bg.add(woman); selectBox.add(man); selectBox.add(woman); jPanel.add(sex); jPanel.add(selectBox); } /* * 设置面板四 */ private void setJPanel4(JPanel jPanel) { // TODO 自动生成的方法存根 jPanel.setPreferredSize(new Dimension(700, 150)); FlowLayout flowLayout = new FlowLayout(FlowLayout.CENTER, 50, 10); jPanel.setLayout(flowLayout); jPanel.setLayout(flowLayout); JButton sublite = new JButton("提交"); JButton reset = new JButton("重置"); sublite.addActionListener((e) -> valiData()); reset.addActionListener((e) -> Reset()); jPanel.add(sublite); jPanel.add(reset); } /* * 提交数据 */ private void valiData() { // 拿到数据(控制台输出) String name = fieldname.getText().toString().trim(); String diploma = comboBox.getSelectedItem().toString().trim(); String address = fieldadress.getText().toString().trim(); System.out.println("姓名:"+name); System.out.println("学历:"+diploma); String hobbystring=""; if (sing.isSelected()) { hobbystring+="唱歌 "; } if (dance.isSelected()) { hobbystring+="跳舞 "; } if (draw.isSelected()) { hobbystring+="画画 "; } System.out.println("地址:"+(address)); if (man.isSelected()) { System.out.println("性别:"+"男"); } if (woman.isSelected()) { System.out.println("性别:"+"女"); } System.out.println("爱好:"+hobbystring); } /* * 重置 */ private void Reset() { // TODO 自动生成的方法存根 fieldadress.setText(null); fieldname.setText(null); comboBox.setSelectedIndex(0); sing.setSelected(false); dance.setSelected(false); draw.setSelected(false); bg.clearSelection(); } }
package bounceThread; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.Window; public class WinCenter { public static void center(Window win){ Toolkit tkit = Toolkit.getDefaultToolkit(); Dimension sSize = tkit.getScreenSize(); Dimension wSize = win.getSize(); if(wSize.height > sSize.height){ wSize.height = sSize.height; } if(wSize.width > sSize.width){ wSize.width = sSize.width; } win.setLocation((sSize.width - wSize.width)/ 2, (sSize.height - wSize.height)/ 2); } }
运行结果:
2.创建两个线程,每个线程按顺序输出5次“你好”,每个“你好”要标明来自哪个线程及其顺序号。
package 小陈; class Lefthand extends Thread { public void run() { for (int i = 1; i <= 5; i++) { System.out.println(i+":a.你好!"); try { sleep(300); } 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(i+":b.你好!"); 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(); } }
运行结果:
3. 完善实验十五 GUI综合编程练习程序。
身份证:
package bounceThread; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import javax.swing.*; public class Main extends JFrame { private static ArrayList<Card> cardlist; private static ArrayList<Card> list; private JPanel panel; private JPanel Panel1; private static final int DEFAULT_WITH = 600; private static final int DEFAULT_HEIGHT = 300; public Main() { cardlist = new ArrayList<>(); Scanner scanner = new Scanner(System.in); File file = new File("D:\身份证号.txt"); try { FileInputStream fis = new FileInputStream(file); BufferedReader in = new BufferedReader(new InputStreamReader(fis)); String temp = null; while ((temp = in.readLine()) != null) { Scanner linescanner = new Scanner(temp); linescanner.useDelimiter(" "); String name = linescanner.next(); String id = linescanner.next(); String sex = linescanner.next(); String age = linescanner.next(); String area = linescanner.nextLine(); Card card = new Card(); card.setName(name); card.setId(id); card.setSex(sex); int a = Integer.parseInt(age); card.setAge(a); card.setArea(area); cardlist.add(card); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block System.out.println("信息文件找不到"); e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block System.out.println("信息文件读取错误"); e.printStackTrace(); } panel = new JPanel(); panel.setLayout(new BorderLayout()); JTextArea jt = new JTextArea(); panel.add(jt); add(panel, BorderLayout.NORTH); Panel1 = new JPanel(); Panel1.setLayout(new GridLayout(1, 9)); JButton jButton = new JButton("字典排序"); JButton jButton1 = new JButton("年龄最大和年龄最小"); JLabel lab = new JLabel("寻找老乡:", Label.LEFT); JTextField jt1 = new JTextField(); JLabel lab1 = new JLabel("寻找年龄相近的人:", Label.LEFT); JTextField jt2 = new JTextField(); JLabel lab2 = new JLabel("输入你的身份证号码:", Label.LEFT); JTextField jt3 = new JTextField(); JButton jButton2 = new JButton("退出"); jButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO 自动生成的方法存根 Collections.sort(cardlist); jt.setText(cardlist.toString()); } }); jButton1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO 自动生成的方法存根 int max = 0, min = 100; int j, k1 = 0, k2 = 0; for (int i = 1; i < cardlist.size(); i++) { j = cardlist.get(i).getAge(); if (j > max) { max = j; k1 = i; } if (j < min) { min = j; k2 = i; } } jt.setText("年龄最大:" + cardlist.get(k1) + "年龄最小:" + cardlist.get(k2)); } }); jButton2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); System.exit(0); } }); jt1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String find = jt1.getText(); String text = ""; String place = find.substring(0, 3); for (int i = 0; i < cardlist.size(); i++) { if (cardlist.get(i).getArea().substring(1, 4).equals(place)) { text += " " + cardlist.get(i); jt.setText("老乡:" + text); } } } }); jt2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String yourage = jt2.getText(); int a = Integer.parseInt(yourage); int near = agenear(a); jt.setText("年龄相近:" + cardlist.get(near)); } }); jt3.addKeyListener(new KeyAdapter() { public void keyTyped(KeyEvent e) { // TODO 自动生成的方法存根 list = new ArrayList<>(); Collections.sort(cardlist); String key = jt3.getText(); for (int i = 1; i < cardlist.size(); i++) { if (cardlist.get(i).getId().contains(key)) { list.add(cardlist.get(i)); jt.setText("你可能是: " + list); } } } }); Panel1.add(jButton); Panel1.add(jButton1); Panel1.add(lab); Panel1.add(jt1); Panel1.add(lab1); Panel1.add(jt2); Panel1.add(lab2); Panel1.add(jt3); Panel1.add(jButton2); add(Panel1, BorderLayout.SOUTH); setSize(DEFAULT_WITH, DEFAULT_HEIGHT); } public static int agenear(int age) { int j = 0, min = 100, value = 0, k = 0; for (int i = 0; i < cardlist.size(); i++) { value = cardlist.get(i).getAge() - age; if (value < 0) value = -value; if (value < min) { min = value; k = i; } } return k; } }
package bounceThread; public class Card implements Comparable<Card> { private String name; private String id; private String sex; private int age; private String area; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getArea() { return area; } public void setArea(String area) { this.area = area; } public int compareTo(Card c) { return this.name.compareTo(c.getName()); } public String toString() { return name + " " + id + " " + sex + " " + age + " " + area + " "; } }
package bounceThread; import java.awt.*; import javax.swing.*; public class CardTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new Main(); frame.setTitle("身份证"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
计算器:
package bounceThread; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import javax.swing.*; public class Demo extends JFrame { int i = 0, i1 = 0, k = 0, sum = 0; private PrintWriter out = null; private String[] c1 = new String[10]; private String[] c2 = new String[10]; public Demo() { JPanel panel = new JPanel(); panel.setLayout(new GridLayout(1, 3)); JTextArea jt1 = new JTextArea(); JTextField jt2 = new JTextField(); JTextArea jt3 = new JTextArea(); panel.add(jt1); panel.add(jt2); panel.add(jt3); add(panel, BorderLayout.NORTH); JPanel panel1 = new JPanel(); panel1.setLayout(new GridLayout(1, 2)); Button button1 = new Button("生成题目"); Button button2 = new Button("生成文件"); panel1.add(button1); panel1.add(button2); add(panel1, BorderLayout.SOUTH); setSize(600, 300); button1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jt2.setText(null); jt3.setText(null); if (i < 10) { int a = (int) (Math.random() * 100); int b = (int) (Math.random() * 100); int m = (int) Math.round(Math.random() * 3); switch (m) { case 0: while (b == 0 || a % b != 0) { b = (int) Math.round(Math.random() * 100); a = (int) Math.round(Math.random() * 100); } jt1.setText(i + 1 + ": " + a + "/" + b + "="); c1[i] = jt1.getText(); k = a / b; i++; break; case 1: jt1.setText(i + 1 + ": " + a + "*" + b + "="); c1[i] = jt1.getText(); k = a * b; i++; break; case 2: jt1.setText(i + 1 + ": " + a + "+" + b + "="); c1[i] = jt1.getText(); k = a + b; i++; break; case 3: while (a < b) { int x = a; a = b; b = x; } jt1.setText(i + 1 + ": " + a + "-" + b + "="); c1[i] = jt1.getText(); k = a - b; i++; break; } } } }); jt2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (i < 11) { int find = Integer.parseInt(jt2.getText()); String d = jt2.getText().toString().trim(); if (jt2.getText() != "") { if (find == k) { sum += 10; jt3.setText("答案正确"); } else jt3.setText("答案错误"); } c2[i1] = d; i1++; } } }); button2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { out = new PrintWriter("text.txt"); } catch (FileNotFoundException e1) { e1.printStackTrace(); } for (int counter = 0; counter < 10; counter++) { out.println(c1[counter] + c2[counter]); } out.println("成绩为" + sum); out.close(); } }); } }
package bounceThread; import java.awt.*; import javax.swing.*; public class DemoTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new Demo(); frame.setTitle("计算器"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
个人总结:本周主要学习了并发这一章,主要内容是线程的相关知识。对程序一的认识比较清晰,对优先级的认识比较模糊,还需要继续学习。