201771010123汪慧和《面向物件程式設計Java》第十六週實驗總結
一、理論部分
1、程式與程序的概念
‐程式是一段靜態的程式碼,它是應用程式執行的藍本。
‐程序是程式的一次動態執行,它對應了從程式碼載入、執行至執行完畢的一個完整過程。
‐作業系統為每個程序分配一段獨立的記憶體空間和系統資源,包括:程式碼資料以及堆疊等資源。每 一個程序的內部資料和狀態都是完全獨立的。
‐多工作業系統中,程序切換對CPU資源消耗較大。
2、多執行緒的概念
‐多執行緒是程序執行過程中產生的多條執行線索。
‐執行緒是比程序執行更小的單位。
‐執行緒不能獨立存在,必須存在於程序中,同一程序的各執行緒間共享程序空間的資料。
‐每個執行緒有它自身的產生、存在和消亡的過程, 是一個動態的概念。
‐多執行緒意味著一個程式的多行語句可以看上去幾 乎在同一時間內同時執行。
‐執行緒建立、銷燬和切換的負荷遠小於程序,又稱為輕量級程序(lightweight process)。
3、Java實現多執行緒有兩種途徑:
‐建立Thread類的子類
‐在程式中定義實現Runnable介面的類
4、用Thread類子類建立執行緒
首先需從Thread類派生出一個子類,在該子類中重寫run()方法。
class hand extends Thread
{
public void run()
{……}
}
5、用Thread類的子類建立多執行緒的關鍵性操作
–定義Thread類的子類並實現使用者執行緒操作,即 run()方法的實現。
–在適當的時候啟動執行緒。
由於Java只支援單重繼承,用這種方法定義的類不可再繼承其他父類。
6、用Runnable()介面實現執行緒
- 首先設計一個實現Runnable介面的類;
- 然後在類中根據需要重寫run方法;
- 再建立該類物件,以此物件為引數建立Thread 類的物件;
- 呼叫Thread類物件的start方法啟動執行緒,將 CPU執行權轉交到run方法。
7、執行緒的終止
-當執行緒的run方法執行方法體中最後一條語句後,或者出現了在run方法中沒有捕獲的異常時,執行緒將終止,讓出CPU使用權。
- 呼叫interrupt()方法也可終止執行緒。
void interrupt()
– 向一個執行緒傳送一箇中斷請求,同時把這個執行緒的“interrupted”狀態置為true。
– 若該執行緒處於 blocked 狀態 ,會丟擲 InterruptedException。
8、測試執行緒是否被中斷的方法
Java提供了幾個用於測試執行緒是否被中斷的方法。
-static boolean interrupted()
– 檢測當前執行緒是否已被中斷 ,並重置狀態 “interrupted”值為false。
-boolean isInterrupted()
– 檢測當前執行緒是否已被中斷 ,不改變狀態 “interrupted”值 。
9、執行緒的狀態
-利用各執行緒的狀態變換,可以控制各個執行緒輪流使用CPU,體現多執行緒的並行性特徵。
-執行緒有如下7種狀態:
➢ New (新建)
➢ Runnable (可執行)
➢ Running(執行)
➢ Blocked (被阻塞)
➢ Waiting (等待)
➢ Timed waiting (計時等待)
➢ Terminated (被終止)
10、新建立執行緒
-new(新建)
執行緒物件剛剛建立,還沒有啟動,此時執行緒還處於不可執行狀態。例如: Thread thread=new Thread(r); 此時執行緒thread處於新建狀態,有了相應的記憶體空間以及其它資源。
11、可執行執行緒
- runnable(可執行狀態)
➢ 此時執行緒已經啟動,處於執行緒的run()方法之中。
➢ 此時的執行緒可能執行,也可能不執行,只要 CPU一空閒,馬上就會執行。
➢ 呼叫執行緒的start()方法可使執行緒處於“可執行”狀態。例如: thread.start();
12、被阻塞執行緒和等待執行緒
- blocked (被阻塞)
➢ 一個正在執行的執行緒因特殊原因,被暫停執行, 進入阻塞狀態。
➢ 阻塞時執行緒不能進入佇列排隊,必須等到引起阻塞的原因消除,才可重新進入排隊佇列。
➢ 引起阻塞的原因很多,不同原因要用不同的方法解除。
-sleep(),wait()是兩個常用引起執行緒阻塞的方法。
13、執行緒阻塞的三種情況
- 等待阻塞 -- 通過呼叫執行緒的wait()方法,讓執行緒等待某工作的完成。
- 同步阻塞 -- 執行緒在獲取synchronized同步鎖失敗(因為鎖被其它執行緒所佔用),它會進入同步阻塞狀態。
-其他阻塞 -- 通過呼叫執行緒的sleep()或join() 或發出了I/O請求時,執行緒會進入到阻塞狀態。當 sleep()狀態超時、join()等待執行緒終止或者超 時、或者I/O處理完畢時,執行緒重新轉入就緒狀態。
14、被終止的執行緒
Terminated (被終止) 執行緒被終止的原因有二:
➢ 一是run()方法中最後一個語句執行完畢而自然死亡。
➢ 二是因為一個沒有捕獲的異常終止了run方法而意外死亡。
➢ 可以呼叫執行緒的 stop 方 法 殺 死 一 個 線 程(thread.stop();),但是,stop方法已過時, 不要在自己的程式碼中呼叫它。
15、多執行緒排程
-Java 的執行緒排程採用優先順序策略:
➢ 優先順序高的先執行,優先順序低的後執行;
➢ 多執行緒系統會自動為每個執行緒分配一個優先順序,預設時,繼承其父類的優先順序;
➢ 任務緊急的執行緒,其優先順序較高;
➢ 同優先順序的執行緒按“先進先出”的佇列原則;
16、Thread類有三個與執行緒優先順序有關的靜態量:
➢ MAX_PRIORITY:最大優先權,值為10;
➢ MIN_PRIORITY:最小優先權,值為1;
➢ NORM _PRIORITY:預設優先權,值為5。
二、實驗部分
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(); } } |
用Runnable介面改造程式的程式:
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(); } }
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 lefthand = new Lefthand(); Thread left=new Thread(lefthand); left.start(); Runnable righthand = new Righthand(); Thread 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.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); } }
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.*; 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()); Thread.sleep(DELAY); } } catch (InterruptedException e) { } } }
實驗結果如下圖示:
說明:此程式的close按鈕不起作用。
改進後的程式:
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); } }
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.*; 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 = () -> { 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(); } }
實驗結果如下圖所示:
說明:改進後的程式,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()+"已計算完畢!"); } } |
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++);// 執行空語句,用來延時,也可以換成sleep,sleep會釋放CPU,會丟擲異常 System.out.println(getName() + "執行緒的優先順序是" + getPriority() + "已計算完畢!"); } }
實驗結果如下圖所示:
測試程式4
l 教材642頁程式模擬一個有若干賬戶的銀行,隨機地生成在這些賬戶之間轉移錢款的交易。每一個賬戶有一個執行緒。在每一筆交易中,會從執行緒所服務的賬戶中隨機轉移一定數目的錢款到另一個隨機賬戶。
l 在Elipse環境下除錯教材642頁程式14-5、14-6,結合程式執行結果理解程式;
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); } /** * 把錢從一個賬戶轉到另一個賬戶。 * @param 從賬戶轉出 * @param 到賬轉到 * @param 轉帳金額 */ 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; } }
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(); } } }
實驗結果如下圖所示:
綜合程式設計練習
程式設計練習1
1. 設計一個使用者資訊採集程式,要求如下:
(1) 使用者資訊輸入介面如下圖所示:
(2) 使用者點選提交按鈕時,使用者輸入資訊顯示控制檯介面;
(3) 使用者點選重置按鈕後,清空使用者已輸入資訊;
(4) 點選視窗關閉,程式退出。
package test1; import java.awt.EventQueue; import javax.swing.JFrame; public class Mian { public static void main(String[] args) { EventQueue.invokeLater(() -> { DemoJFrame page = new DemoJFrame(); }); } }
package test1; 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 test1; 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 nan; private JRadioButton nv; private JCheckBox sing; private JCheckBox dance; private JCheckBox draw; public DemoJFrame() { // 設定視窗大小 this.setSize(800, 400); // 設定可見性 this.setVisible(true); // 設定標題 this.setTitle("Student Detail"); // 設定關閉操作 this.setDefaultCloseOperation(EXIT_ON_CLOSE); // 設定視窗居中 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:"); name.setSize(100, 50); fieldname = new JTextField(""); fieldname.setSize(80, 20); JLabel study = new JLabel("Qualification:"); comboBox = new JComboBox(); comboBox.addItem("Graduate"); comboBox.addItem("senior"); comboBox.addItem("Undergraduate"); 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("Address:"); fieldadress = new JTextField(); fieldadress.setPreferredSize(new Dimension(150, 50)); JLabel study = new JLabel("Hobby:"); JPanel selectBox = new JPanel(); selectBox.setBorder(BorderFactory.createTitledBorder("")); selectBox.setLayout(new GridLayout(3, 1)); sing = new JCheckBox("Singing"); dance = new JCheckBox("Dancing"); draw = new JCheckBox("Reading"); 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("Sex:"); JPanel selectBox = new JPanel(); selectBox.setBorder(BorderFactory.createTitledBorder("")); selectBox.setLayout(new GridLayout(2, 1)); bg = new ButtonGroup(); nan = new JRadioButton("Male"); nv = new JRadioButton("Female"); bg.add(nan); bg.add(nv); selectBox.add(nan); selectBox.add(nv); 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("Validate"); JButton reset = new JButton("Reset"); sublite.addActionListener((e) -> valiData()); reset.addActionListener((e) -> Reset()); jPanel.add(sublite); jPanel.add(reset); } /* * 提交資料 */ private void valiData() { // 拿到資料 String name = fieldname.getText().toString().trim(); String xueli = comboBox.getSelectedItem().toString().trim(); String address = fieldadress.getText().toString().trim(); System.out.println(name); System.out.println(xueli); String hobbystring=""; if (sing.isSelected()) { hobbystring+="Singing "; } if (dance.isSelected()) { hobbystring+="Dancing "; } if (draw.isSelected()) { hobbystring+="Reading "; } System.out.println(address); if (nan.isSelected()) { System.out.println("Male"); } if (nv.isSelected()) { System.out.println("Female"); } System.out.println(hobbystring); } /* * 重置 */ private void Reset() { fieldadress.setText(null); fieldname.setText(null); comboBox.setSelectedIndex(0); sing.setSelected(false); dance.setSelected(false); draw.setSelected(false); bg.clearSelection(); } }
實驗結果如下圖所示:
2.建立兩個執行緒,每個執行緒按順序輸出5次“你好”,每個“你好”要標明來自哪個執行緒及其順序號。
package test2; class Lefthand extends Thread { public void run() { for(int i=0;i<=4;i++) { System.out.println("1.你好"); try{ sleep(500); } catch(InterruptedException e) { System.out.println("Lefthand error.");} } } } class Righthand extends Thread { public void run() { for(int i=0;i<=4;i++) { System.out.println("2.你好"); 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綜合程式設計練習程式。
實驗一
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); }); } }
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