實驗十六 線程技術java
實驗時間 2017-12-8編程
1、實驗目的與要求安全
(1) 掌握線程概念;數據結構
(2) 掌握線程建立的兩種技術;框架
(3) 理解和掌握線程的優先級屬性及調度方法;dom
(4) 掌握線程同步的概念及實現技術;學習
2、實驗內容和步驟測試
實驗1:測試程序並進行代碼註釋。ui
測試程序1:spa
l 在elipse IDE中調試運行ThreadTest,結合程序運行結果理解程序;
l 掌握線程概念;
l 掌握用Thread的擴展類實現線程的方法;
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(); } } |
l 利用Runnable接口改造程序,掌握用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 M { public static void main(String[] args) { Runnable r=new Lefthand(); Runnable r1=new Righthand(); Thread t=new Thread(r); Thread t1=new Thread(r1); t.start(); t1.start(); } }
測試結果以下所示
測試程序2:
l 在Elipse環境下調試教材625頁程序14-一、14-2 、14-3,結合程序運行結果理解程序;
l 對比兩個程序,理解線程的概念和用途;
l 掌握線程建立的兩種技術。
package bounce; 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); // 擦除背景 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.*; 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(); } /** * 將按鈕添加到容器中 *按鈕標題 * 按鈕的動做監聽器 */ 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) { } } }
package bounce; 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); } }
測試結果以下所示
在Elipse環境下調試教材631頁程序14-4,結合程序運行結果理解程序;
package bounceThread; 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(); } 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(); } }
測試結果以下所示
測試程序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()+"已計算完畢!"); } } |
測試結果以下所示
測試程序4
l 教材642頁程序模擬一個有若干帳戶的銀行,隨機地生成在這些帳戶之間轉移錢款的交易。每個帳戶有一個線程。在每一筆交易中,會從線程所服務的帳戶中隨機轉移必定數目的錢款到另外一個隨機帳戶。
l 在Elipse環境下調試教材642頁程序14-五、14-6,結合程序運行結果理解程序;
package unsynch; /** * 當多個線程訪問一個數據結構時,這個程序顯示數據損壞。 */ 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.*; public class Bank { private final double[] accounts; /** * @參數n表示帳戶數量 * @每一個賬戶的初始餘額 */ 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()); } /** * 獲取全部賬戶餘額的總和。 * 返回總餘額 */ public double getTotalBalance() { double sum = 0; for (double a : accounts) sum += a; return sum; } /** *獲取銀行中的賬戶編號. * 返回帳號 */ public int size() { return accounts.length; } }
測試結果以下所示
綜合編程練習
編程練習1
(1) 用戶信息輸入界面以下圖所示:
(2) 用戶點擊提交按鈕時,用戶輸入信息顯示控制檯界面;
(3) 用戶點擊重置按鈕後,清空用戶已輸入信息;
(4) 點擊窗口關閉,程序退出。
import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.*; import javax.swing.*; public class Guiwork { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new FrameTest(); frame.setTitle("produce by 王海珍"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } class FrameTest extends JFrame { private JPanel panel; private JTextArea text,text2; private JRadioButton JRadioButton1,JRadioButton2; private ButtonGroup ButtonGroup; private JLabel JLabel; private JCheckBox h1,h2,h3; private JComboBox<String> JComboBox; private JButton Button,Button2; public FrameTest() { setSize(700,500); panel=new JPanel(); panel.setLayout(null); ButtonGroup=new ButtonGroup(); JRadioButton1=new JRadioButton("Male",false); JRadioButton1.setBounds(150,330, 80, 50); JRadioButton2=new JRadioButton("Female",false); JRadioButton2.setBounds(150,300, 80,50); ButtonGroup.add(JRadioButton1); ButtonGroup.add(JRadioButton2); addJLabel("sex:",100,300); addJLabel("name:",100,50); addJLabel("address:",100,150); addJLabel("Qualification:",400,50); addJLabel("Hobby:",400,150); text=new JTextArea(1,1);text.setBounds(150,70, 120, 30);text.setLineWrap(true); text2=new JTextArea(5,3);text2.setBounds(150,160, 130, 100);text2.setLineWrap(true); h1=new JCheckBox("Reading");h1.setBounds(450,160,100,30); h2=new JCheckBox("dancing");h2.setBounds(450,180,100,30); h3=new JCheckBox("singing");h3.setBounds(450,200,100,30); JComboBox=new JComboBox<>(); JComboBox.addItem("Graduate"); JComboBox.addItem("Graduate1"); JComboBox.addItem("Graduate2"); JComboBox.setBounds(500,65, 100, 20); Button = new JButton("提交");Button.setBounds(200, 400, 100, 35); Button2 = new JButton("重置");Button2.setBounds(400, 400, 100, 35); Button.addActionListener(new Action1()); Button2.addActionListener(new Action2()); panel.add(h1); panel.add(h2); panel.add(h3); panel.add(Button); panel.add(Button2); panel.add(JComboBox); panel.add(text); 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:"+text.getText()+"\n"+"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("\n"+"sex:"); if(JRadioButton1.isSelected()==true)System.out.println(JRadioButton1.getText()); if(JRadioButton2.isSelected()==true)System.out.println(JRadioButton2.getText()); System.out.println("\n"); } } private class Action2 implements ActionListener { public void actionPerformed(ActionEvent event) { text.setText(null); text2.setText(null); h1.setSelected(false); h2.setSelected(false); h3.setSelected(false); ButtonGroup.clearSelection(); JComboBox.setSelectedIndex(0); } } }
2.建立兩個線程,每一個線程按順序輸出5次「你好」,每一個「你好」要標明來自哪一個線程及其順序號。
class Lefthand extends Thread { public void run() { for (int i = 1; i <= 5; i++) { System.out.println(i+":1.你好!"); 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+":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(); } }
結果以下所示
第三部分 實驗總結
本週實驗的主要學習內容是關於線程的瞭解,關於什麼是線程,線程安全的集合,中斷線程,線程的狀態等幾個方面進行了學習。而經過本次實驗感受本身也有了必定的進步,固然了在作本次實驗的時候也有參考其餘同窗的優秀的做業成果的。