博文正文開頭格式:(2分)
隨筆博文正文內(nèi)容包括: 第一部分:總結(jié)教材14.1-14.3知識內(nèi)容(20分) 一、程序與進程的概念 1、程序是一段靜態(tài)的代碼,它是應(yīng)用程序執(zhí)行的藍 本。 2、進程是程序的一次動態(tài)執(zhí)行,它對應(yīng)了從代碼加載、執(zhí)行至執(zhí)行完畢的一個完整過程。 3、操作系統(tǒng)為每個進程分配一段獨立的內(nèi)存空間和系統(tǒng)資源,包括:代碼數(shù)據(jù)以及堆棧等資源。每一個進程的內(nèi)部數(shù)據(jù)和狀態(tài)都是完全獨立的。 4、多任務(wù)操作系統(tǒng)中,進程切換對CPU資源消耗較大。 5、一個程序至少有一個進程,一個進程至少有一個線程。 6、線程的劃分尺度小于進程,使得多進程程序的并發(fā)性高。 7、進程在執(zhí)行過程中擁有獨立的內(nèi)存單元,而多個線程共享內(nèi)存,從而極大地提高了程序的運行效率。 8、線程在執(zhí)行過程中與進程還是有區(qū)別的。每個獨立的線程有一個程序運行的入口、順序執(zhí)行序列和程序的出口。但是線程不能夠獨立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個線程執(zhí)行控制。 9、從邏輯角度來看,多線程的意義在于一個應(yīng)用程序中,有多個執(zhí)行部分可以同時執(zhí)行。但操作系統(tǒng)并沒有將多個線程看做多個獨立的應(yīng)用,來實現(xiàn)進程的調(diào)度和管理以及資源分配。這就是進程和線程的重要區(qū)別。 二、多線程的概念 1、多線程是進程執(zhí)行過程中產(chǎn)生的多條執(zhí)行線索。 2、線程是比進程執(zhí)行更小的單位。 3、線程不能獨立存在,必須存在于進程中,同一進 程的各線程間共享進程空間的數(shù)據(jù)。 4、每個線程有它自身的產(chǎn)生、存在和消亡的過程, 是一個動態(tài)的概念。 5、多線程意味著一個程序的多行語句可以看上去幾 乎在同一時間內(nèi)同時運行。 6、線程創(chuàng)建、銷毀和切換的負荷遠小于進程,又稱為輕量級進程(lightweight process)。 7、Java實現(xiàn)多線程有兩種途徑: 1)創(chuàng)建Thread類的子類 2)在程序中定義實現(xiàn)Runnable接口的類 三、Java中的線程 在Java中,“線程”指兩件不同的事情: 1、java.lang.Thread類的一個實例; 2、線程的執(zhí)行。 在 Java程序中,有兩種方法創(chuàng)建線程: 一是對 Thread 類進行派生并覆蓋 run方法; 二是通過實現(xiàn)Runnable接口創(chuàng)建。 使用java.lang.Thread類或者java.lang.Runnable接口編寫代碼來定義、實例化和啟動新線程。 一個Thread類實例只是一個對象,像Java中的任何其他對象一樣,具有變量和方法,生死于堆上。 Java中,每個線程都有一個調(diào)用棧,即使不在程序中創(chuàng)建任何新的線程,線程也在后臺運行著。 一個Java應(yīng)用總是從main()方法開始運行,main()方法運行在一個線程內(nèi),他被稱為主線程。 一旦創(chuàng)建一個新的線程,就產(chǎn)生一個新的調(diào)用棧。 線程總體分兩類:用戶線程和守候線程。 當所有用戶線程執(zhí)行完畢的時候,JVM自動關(guān)閉。但是守候線程卻不獨立于JVM,守候線程一般是由操作系統(tǒng)或者用戶自己創(chuàng)建的。 Java線程:創(chuàng)建與啟動 1、定義線程 擴展java.lang.Thread類。 此類中有個run()方法,應(yīng)該注意其用法:public void run() 如果該線程是使用獨立的Runnable運行對象構(gòu)造的,則調(diào)用該Runnable對象的run方法;否則,該方法不執(zhí)行任何操作并返回。 Thread的子類應(yīng)該重寫該方法。 2、實現(xiàn)java.lang.Runnable接口。 void run() 使用實現(xiàn)接口Runnable的對象創(chuàng)建一個線程時,啟動該線程將導(dǎo)致在獨立執(zhí)行的線程中調(diào)用對象的run方法。 方法run的常規(guī)協(xié)定是,它可能執(zhí)行任何所需的操作。 3、實例化線程 2、如果是實現(xiàn)了java.lang.Runnable接口的類,則用Thread的構(gòu)造方法: [java] view plain copy Thread(Runnabletarget) Thread(Runnabletarget, String name) Thread(ThreadGroupgroup, Runnable target) Thread(ThreadGroupgroup, Runnable target, String name) Thread(ThreadGroupgroup, Runnable target, String name, long stackSize) 其中: Runnable target:實現(xiàn)了Runnable接口的類的實例。 Thread類也實現(xiàn)了Runnable接口,因此,從Thread類繼承的類的實例也可以作為target傳入這個構(gòu)造方法。 四、線程狀態(tài) 線程的狀態(tài)轉(zhuǎn)換是線程控制的基礎(chǔ)。線程狀態(tài)總的可以分為五大狀態(tài)。用一個圖來描述如下: 1、新狀態(tài):線程對象已經(jīng)創(chuàng)建,還沒有在其上調(diào)用start()方法。 2、可運行狀態(tài):當線程有資格運行,但調(diào)度程序還沒有把它選定為運行線程時線程所處的狀態(tài)。當start()方法調(diào)用時,線程首先進入可運行狀態(tài)。在線程運行之后或者從阻塞、等待或睡眠狀態(tài)回來后,也返回到可運行狀態(tài)。 3、運行狀態(tài):線程調(diào)度程序從可運行池中選擇一個線程作為當前線程時線程所處的狀態(tài)。這也是線程進入運行狀態(tài)的唯一一種方式。 4、等待/阻塞/睡眠狀態(tài):這是線程有資格運行時它所處的狀態(tài)。實際上這個三狀態(tài)組合為一種,其共同點是:線程仍舊是活的,但是當前沒有條件運行。換句話說,它是可運行的,但是如果某件事件出現(xiàn),他可能返回到可運行狀態(tài)。 5、死亡態(tài):當線程的run()方法完成時就認為它死去。這個線程對象也許是活的,但是,它已經(jīng)不是一個單獨執(zhí)行的線程。線程一旦死亡,就不能復(fù)生。如果在一個死去的線程上調(diào)用start()方法,會拋出java.lang.IllegalThreadStateException異常。 五、啟動線程 2、在調(diào)用start()方法之前:線程處于新狀態(tài)中,新狀態(tài)指有一個Thread對象,但還沒有一個真正的線程。 3、在調(diào)用start()方法之后:發(fā)生了一系列復(fù)雜的事情—— 4、啟動新的執(zhí)行線程(具有新的調(diào)用棧); 5、該線程從新狀態(tài)轉(zhuǎn)移到可運行狀態(tài); 6、當該線程獲得機會執(zhí)行時,其目標run()方法將運行。 7、注意:對Java來說,run()方法沒有任何特別之處。像main()方法一樣,它只是新線程知道調(diào)用的方法名稱(和簽名)。因此,在Runnable上或者Thread上調(diào)用run方法是合法的。但并不啟動新的線程。 六、線程的終止 1、當線程的run方法執(zhí)行方法體中最后一條語句后, 或者出現(xiàn)了在run方法中沒有捕獲的異常時,線 程將終止,讓出CPU使用權(quán)。 2、調(diào)用interrupt()方法也可終止線程。 void interrupt() – 1)向一個線程發(fā)送一個中斷請求,同時把這個線 程的“interrupted”狀態(tài)置為true。 2)若該線程處于blocked 狀態(tài), 會拋出 InterruptedException。 六、測試線程是否被中斷的方法 Java提供了幾個用于測試線程是否被中斷的方法。 * static boolean interrupted() – 檢測當前線程是否已被中斷, 并重置狀態(tài) “interrupted”值為false。 * boolean isInterrupted() – 檢測當前線程是否已被中斷, 不改變狀態(tài) “interrupted”值 。 六、守護線程 * 守護線程的惟一用途是為其他線程提供服務(wù)。例 如計時線程。 * 若JVM的運行任務(wù)只剩下守護線程時,JVM就退 出了。 * 在一個線程啟動之前,調(diào)用setDaemon方法可 將線程轉(zhuǎn)換為守護線程(daemon thread)。 例如: setDaemon(true); 第二部分、實驗部分 實驗1: 導(dǎo)入第13章示例程序,測試程序并進行代碼注釋。 測試程序1 l 在elipse IDE中調(diào)試運行教材585頁程序13-1,結(jié)合程序運行結(jié)果理解程序; l 將所生成的JAR文件移到另外一個不同的目錄中,再運行該歸檔文件,以便確認程序是從JAR文件中,而不是從當前目錄中讀取的資源。 l 掌握創(chuàng)建JAR文件的方法; 程序代碼如下: package resource; import java.awt.*; import java.io.*; import java.net.*; import java.util.*; import javax.swing.*; /** * @version 1.41 2015-06-12 * @author Cay Horstmann */ public class ResourceTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new ResourceTestFrame(); frame.setTitle("ResourceTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } /** * A frame that loads image and text resources. */ class ResourceTestFrame extends JFrame { private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 300;//設(shè)置組件大小 public ResourceTestFrame() { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); //利用about.gif圖像文件制作圖標 //在找到ResourceTest類的地方查找about.gif文件 URL aboutURL = getClass().getResource("about.gif"); Image img = new ImageIcon(aboutURL).getImage(); setIconImage(img); JTextArea textArea = new JTextArea(); //讀取about.txt文件 InputStream stream = getClass().getResourceAsStream("about.txt"); try (Scanner in = new Scanner(stream, "UTF-8")) { while (in.hasNext()) textArea.append(in.nextLine() "\n"); } add(textArea); } } Main-Class: resource.ResourceTest Core Java: Fundamentals 10th Edition Cay Horstmann and Gary Cornell Copyright 漏 2016 Prentice-Hall 運行結(jié)果如下:
歸檔及之后運行截圖:
雙擊打開:
創(chuàng)建JAR文件的方法: 一、制作只含有字節(jié)碼文件的jar包 1、最簡單的jar包——直接輸出內(nèi)容 2、含有兩個類的jar包——通過調(diào)用輸出內(nèi)容 3、有目錄結(jié)構(gòu)的jar包——通過引包并調(diào)用輸出內(nèi)容 二、制作含有jar文件的jar包 1、兩個jar包間相互調(diào)用——調(diào)用jar外的jar輸出內(nèi)容 2、jar包中含有jar包——調(diào)用jar內(nèi)的jar輸出內(nèi)容 三、制作含有資源文件的jar包 1、資源文件在jar包內(nèi)部——讀取jar內(nèi)的文件 2、資源文件在另一個jar包內(nèi)部——讀取另一個jar內(nèi)的文件 3、資源文件在jar包外部——讀取jar外的文件 測試程序2: l 在elipse IDE中調(diào)試運行ThreadTest,結(jié)合程序運行結(jié)果理解程序; l 掌握線程概念; l 掌握用Thread的擴展類實現(xiàn)線程的方法; l 利用Runnable接口改造程序,掌握用Runnable接口創(chuàng)建線程的方法。 class Lefthand extends Thread { public void run() { for(int i=0;i<=5;i ) { System.out.println("You are Students!"); try{ sleep(500); }//輸出第一次后,出現(xiàn)休眠時間為500ms catch(InterruptedException e) { System.out.println("Lefthand error.");} } //for循環(huán)執(zhí)行六次,輸出6次You are Students! } } class Righthand extends Thread { public void run() { for(int i=0;i<=5;i ) { System.out.println("I am a Teacher!"); try{ sleep(300); }//輸出第一次后,出現(xiàn)休眠時間為600ms catch(InterruptedException e) { System.out.println("Righthand error.");} }//for循環(huán)執(zhí)行六次,輸出6次I am a Teacher! } } 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(); } } 改后的程序代碼: 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 fufj { static Thread left; static Thread right; public static void main(String[] args) { Runnable rleft = new Lefthand(); Runnable rright = new Righthand(); left = new Thread(rleft); right = new Thread(rright); left.start(); right.start(); } } 運行結(jié)果如下:
一、定義線程 此類中有個run()方法,應(yīng)該注意其用法:public void run() 如果該線程是使用獨立的Runnable運行對象構(gòu)造的,則調(diào)用該Runnable對象的run方法;否則,該方法不執(zhí)行任何操作并返回。 Thread的子類應(yīng)該重寫該方法。 二、實現(xiàn)java.lang.Runnable接口。 void run() 使用實現(xiàn)接口Runnable的對象創(chuàng)建一個線程時,啟動該線程將導(dǎo)致在獨立執(zhí)行的線程中調(diào)用對象的run方法。 方法run的常規(guī)協(xié)定是,它可能執(zhí)行任何所需的操作。 三、實例化線程 2、如果是實現(xiàn)了java.lang.Runnable接口的類,則用Thread的構(gòu)造方法。 [java] view plain copy Thread(Runnabletarget) Thread(Runnabletarget, String name) Thread(ThreadGroupgroup, Runnable target) Thread(ThreadGroupgroup, Runnable target, String name) Thread(ThreadGroupgroup, Runnable target, String name, long stackSize) 其中: Runnable target:實現(xiàn)了Runnable接口的類的實例。 Thread類也實現(xiàn)了Runnable接口,因此,從Thread類繼承的類的實例也可以作為target傳入這個構(gòu)造方法。 測試程序3: l 在Elipse環(huán)境下調(diào)試教材625頁程序14-1、14-2 、14-3,結(jié)合程序運行結(jié)果理解程序; l 在Elipse環(huán)境下調(diào)試教材631頁程序14-4,結(jié)合程序運行結(jié)果理解程序; l 對比兩個程序,理解線程的概念和用途; 掌握線程創(chuàng)建的兩種技術(shù)。 程序代碼如下: 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<>(); /** * 向組件中添加一個球。 * @param b要添加的球 */ 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; /** * 用顯示彈跳球的組件構(gòu)造框架,以及開始和關(guān)閉按鈕 */ 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 title 按鈕標題 * @param 監(jiān)聽按鈕的操作監(jiān)聽器 */ 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) { } } } 運行結(jié)果如下: package bounceThread; 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 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要添加的球 */ 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; /** * 用顯示彈跳球以及開始和關(guān)閉按鈕的組件構(gòu)建框架 */ 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 title 按鈕標題 * @param listener 按鈕的操作監(jiān)聽器 */ 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(); } } 運行結(jié)果如下: Java提供了線程類Thread來創(chuàng)建多線程的程序。其實,創(chuàng)建線程與創(chuàng)建普通的類的對象的操作是一樣的,而線程就是Thread類或其子類的實例對象。每個Thread對象描述了一個單獨的線程。要產(chǎn)生一個線程,有兩種方法: 1、需要從Java.lang.Thread類派生一個新的線程類,重載它的run()方法; 2、實現(xiàn)Runnalbe接口,重載Runnalbe接口中的run()方法。 實驗2:結(jié)對編程練習(xí):采用GUI界面設(shè)計以下程序,并創(chuàng)建程序歸檔文件。 設(shè)計一個100以內(nèi)整數(shù)小學(xué)生四則運算練習(xí)程序,由計算機隨機產(chǎn)生10道加減乘除練習(xí)題,學(xué)生輸入答案,由程序檢查答案是否正確,每道題正確計10分,錯誤不計分,10道題測試結(jié)束后給出測試總分; 將程序中測試練習(xí)題及學(xué)生答題結(jié)果輸出到文件,文件名為test.txt。 實驗總結(jié):(15分) 通過本周的學(xué)習(xí),我掌握了線程概念;在學(xué)習(xí)過程中,了解了線程創(chuàng)建的兩種技術(shù):用Thread類的子類創(chuàng)建線程以及用Runnable()接口實現(xiàn)線程。理解和掌握了基礎(chǔ)線程的優(yōu)先級屬性及調(diào)度方法;學(xué)會了Java GUI 編程技術(shù)的基礎(chǔ)。本章知識是Java的重點同時也為以后操作系統(tǒng)的學(xué)習(xí)做了一個鋪墊,因此需要更加重視,在以后的學(xué)習(xí)中會繼續(xù)鞏固學(xué)習(xí)。 來源:https://www./content-1-599051.html |
|