張季躍 201771010139《面向對象程序設計(java)》第十六周學習總結java
一、實驗目的與要求編程
(1) 掌握線程概念;dom
(2) 掌握線程建立的兩種技術;學習
(3) 理解和掌握線程的優先級屬性及調度方法;測試
(4) 掌握線程同步的概念及實現技術;this
二、實驗內容和步驟spa
實驗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 Test; 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 Lefthand left; static Righthand right; public static void main(String[] args) { Runnable left1 = new Lefthand(); Runnable right1 = new Righthand() ; Thread left = new Thread(left1); Thread right = new Thread(right1); left.start(); right.start(); } }
實驗結果:
測試程序2:
l 在Elipse環境下調試教材625頁程序14-一、14-2 、14-3,結合程序運行結果理解程序;
l 在Elipse環境下調試教材631頁程序14-4,結合程序運行結果理解程序;
l 對比兩個程序,理解線程的概念和用途;
l 掌握線程建立的兩種技術。
程序代碼:
package ball; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Shows an animated bouncing ball. * @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); }); } }
package balll; import java.awt.*; import java.util.*; import javax.swing.*; /** * The component that draws the balls. * @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<>(); /** * Add a ball to the component. * @param b the ball to add */ 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); } }
package ball; import java.awt.geom.*; /** * A ball that moves and bounces off the edges of a rectangle * @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; } } /** * Gets the shape of the ball at its current position. */ public Ellipse2D getShape() { return new Ellipse2D.Double(x, y, XSIZE, YSIZE); } }
實驗結果:
測試程序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()+"已計算完畢!"); } } |
程序代碼:
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-五、14-6,結合程序運行結果理解程序;
程序代碼:
package unsynch; import java.util.*; /** * A bank with a number of bank accounts. * * @version 1.30 2004-08-01 * @author Cay Horstmann */ 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; } }
package unsynch; /** * This program shows data corruption when multiple threads access a data * structure. * * @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);//分配新的 Thread 對象 t.start();//使該線程開始執行 } } }
測試結果:
綜合編程練習
編程練習1
(1) 用戶信息輸入界面以下圖所示:
(2) 用戶點擊提交按鈕時,用戶輸入信息顯示控制檯界面;
(3) 用戶點擊重置按鈕後,清空用戶已輸入信息;
(4) 點擊窗口關閉,程序退出。
實驗代碼:
package 測試程序5; import java.awt.EventQueue; import javax.swing.JFrame; public class Mian { public static void main(String[] args) { EventQueue.invokeLater(() -> { demo page = new demo(); }); } }
package 測試程序5; 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); } }
package 測試程序5; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; public class demo extends JFrame { public demo() { JPanel panel1 = new JPanel(); panel1.setPreferredSize(new Dimension(700, 45)); panel1.setLayout(new GridLayout(1, 4)); JLabel label1 = new JLabel("Name:"); JTextField j1 = new JTextField(""); JLabel label2 = new JLabel("Qualification:"); JComboBox<Object> j2 = new JComboBox<>(); j2.addItem("Graduate"); j2.addItem("Not Graduate"); panel1.add(label1); panel1.add(j1); panel1.add(label2); panel1.add(j2); JPanel panel2 = new JPanel(); panel2.setPreferredSize(new Dimension(700, 50)); panel2.setLayout(new GridLayout(1, 4)); JLabel label3 = new JLabel("Address:"); JTextArea j3 = new JTextArea(); JLabel label4 = new JLabel("Hobby:"); JPanel p = new JPanel(); p.setLayout(new GridLayout(3, 1)); p.setBorder(BorderFactory.createLineBorder(null)); JCheckBox c1 = new JCheckBox("Reading"); JCheckBox c2 = new JCheckBox("Singing"); JCheckBox c3 = new JCheckBox("Dancing"); p.add(c1); p.add(c2); p.add(c3); panel2.add(label3); panel2.add(j3); panel2.add(label4); panel2.add(p); JPanel panel3 = new JPanel(); panel3.setPreferredSize(new Dimension(700, 150)); FlowLayout flowLayout1 = new FlowLayout(FlowLayout.LEFT, 20, 40); panel3.setLayout(flowLayout1); JLabel label5 = new JLabel("Sex:"); JPanel p1 = new JPanel(); p1.setLayout(new GridLayout(2,1)); p1.setBorder(BorderFactory.createLineBorder(null)); ButtonGroup bu = new ButtonGroup(); JRadioButton jr1 = new JRadioButton("Male"); JRadioButton jr2 = new JRadioButton("Female"); bu.add(jr1); bu.add(jr2); p1.add(jr1); p1.add(jr2); panel3.add(label5); panel3.add(p1); add(panel1); add(panel2); add(panel3); JPanel panel4 = new JPanel(); panel4.setPreferredSize(new Dimension(700, 150)); JButton b1 = new JButton("Validate"); panel4.add(b1); JButton b2 = new JButton("Reset"); panel4.add(b2); add(panel4); FlowLayout flowLayout = new FlowLayout(); this.setLayout(flowLayout); this.setTitle("Students Detail"); this.setBounds(200, 200, 800, 400); this.setVisible(true); this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // TODO 自動生成的方法存根 String xueli = j2.getSelectedItem().toString(); System.out.println("Name:" + j1.getText()); System.out.println("Qualification:" + xueli); String hobbystring = "Hobby:"; if (c1.isSelected()) { hobbystring += "Reading"; } if (c2.isSelected()) { hobbystring += "Singing"; } if (c3.isSelected()) { hobbystring += "Dancing"; } System.out.println("Address:" + j3.getText()); if (jr1.isSelected()) { System.out.println("Sex:Male"); } if (jr2.isSelected()) { System.out.println("Sex:Female"); } System.out.println(hobbystring); } }); b2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // TODO 自動生成的方法存根 j1.setText(null); j3.setText(null); j2.setSelectedIndex(0); c1.setSelected(false); c2.setSelected(false); c3.setSelected(false); bu.clearSelection(); } }); } public static void main(String args[]) { new demo(); } }
實驗結果:
2.建立兩個線程,每一個線程按順序輸出5次「你好」,每一個「你好」要標明來自哪一個線程及其順序號。
實驗代碼:
package demo; class Lefthand extends Thread { public void run() { for (int i = 1; i <= 5; i++) { System.out.println("L:"+i+" 你好!"); 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("R:"+i+" 你好!"); 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綜合編程練習程序。
實驗總結:
在這一週的學習過程當中,我初步瞭解學習了關於線程的知識,並初步掌握了線程建立的兩種方法,但在實驗過程當中,我發現我對線程掌握的並非很熟練,實驗二還好說,但實驗一有不少不懂的地方,仍是參考了許多同窗的代碼才作出來,即便如此,與要求的結果仍是有許多的不一樣。