本次PTA做業題集多線程
java
Thread.sleep
進行休眠?答:BallRunnable
類實現了Runnable
接口,支持了多線程,在其中用於給線程指派任務,在類中的run方法裏經過循環調用小球的移動函數move
和重畫函數repaint
來實現小球的移動軌跡。還有用了Treep.sleep()
來使線程休眠一段時間。
使用Tread.sleep
讓線程進行休眠是爲了延緩線程完成的時間,這樣可讓咱們看到小球的移動,否則不進行休眠的話,這個程序會在一個很快的時間內完成,沒有辦法看到小球的移動軌跡,而且sleep()爲Thread類的靜態方法,調用它不會建立一個新線程。安全
答:Ball.java
完成的兩件事:多線程
move
函數實現小球的移動方法getShape
函數來獲取小球的大小和座標BallComponent
對象也實現了兩件事:dom
其內部的ArrayList用於存放添加的小球
程序中只生成了一個BallComponent對象
經過源代碼能夠看出每按一次start
按鈕,addBall
方法都會啓動一個新線程,所以每一個小球都是在本身的線程中繪製的。eclipse
答:可使用Math.random()方法將ball.java
中的x
、y
、dx
、dy
的值設置成隨機數來達到每次點擊start
時使小球以不一樣位置出發和以不一樣步前進。
函數
並回答:a)經過定義Runnable
接口的實現類來實現多線程程序比經過繼承自Thread
類實現多線程程序有何好處?b) 6-1,6-3,6-11實驗總結。
答:(a).使用實現Runnable
接口來實現多繼承的程序的好處:性能
Runnable
接口適合於資源的共享,以下兩張圖片:
能夠看出,雖然兩個程序中都建立了兩個線程,可是使用Runnable
實現多線程使兩個線程一塊兒完成兩個任務,達到資源共享的目的。
(b).Thread實驗總結
這題中要注意MyThread類有一個有參構造函數,用於接收循環次數,而後要將標識信息放在for循環外,其餘就是普通的打印輸出了。
Runnable實驗總結
這題使用了匿名內部類來實現Runnable接口的run方法來完成程序。獲取當前的線程名字要用Thread.currentThread().getName()
,而後就是按要求輸出就OK了。
PrintTask實驗總結
這題……除了類名和最後輸出的標識信息,其餘都和6-1同樣hhhh學習
Thread t1 = new Thread(() -> { System.out.println(mainThreadName); System.out.println(Thread.currentThread().getName()); System.out.println(Arrays.toString(Thread.class.getInterfaces())); });
答:在Java的Thread類中提供了一個stop()方法用來終止線程,不過,由於這個方法會將執行到一半的線程強行終止,,不能保證線程的資源正確釋放,因此已經被廢棄了。
如今在咱們須要中止一個線程的時候通常使用一個boolean類型的變量來終止線程,這樣可使用while語句,在運行中經過改變boolean標記值來使while循環退出來達到中止線程的做用。
咱們還可使用interrupt
方法來終止線程,可是,這種方法並不適用於一個正在運行的線程,它是用於中止一個受到阻塞的線程,經過使受阻塞的線程拋出異常來退出阻塞的狀態。
所以仍是使用boolean類型的變量來終止線程的方法比較好。測試
這題就是跟着註釋一步步寫下來就能夠了。
CountDownLatch
類是一個同步計數器,構造時傳入int參數,用於表示任務的個數。這個參數是計數器的初始值。
使用Executors
類的newFixedThreadPool
方法能夠建立一個固定線程數的線程池。線程
要想讓ArrayList等達到線程安全,只須要用synchronizedList
修飾list便可。synchronizedList
經過對部分操做加上synchronized
來保證線程安全。
其實只要在Counter類的對id進行操做的兩個方法前加上synchronized
關鍵字就能夠了,它能夠經過給共享資源上一道鎖來使在同一個時間內只容許一個線程訪問共享資源,以此來實現同步機制。
完成題集6-4(互斥訪問)與6-5(同步訪問)
答:還能夠經過synchronized
的同步代碼塊來實現互斥訪問。
修改後的方法以下:
答:同步方法直接在方法名前面加synchonrized
關鍵字來實現對對象的加鎖,而同步代碼塊則是在方法的內部使用synchonrized
關鍵字來加鎖,所以,同步方法的做用範圍比同步代碼塊大,其性能則不如同步代碼塊。
答:實現互斥訪的原理是程序經過給共享資源上一道鎖,讓給定時間內只容許一個線程來訪問共享資源。
下面經過分析一個從書上看到的模擬火車站售票系統的程序來講明同步機制運行時的線程狀態,代碼以下
public class ThreadSafeTest implements Runnable { int num = 10; //設置當前總票數 public void run() { while (true) { synchronized ("") { if (num > 0) { try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } System.out.println("tickets" + --num); } } } } public static void main(String[] args) { ThreadSafeTest t = new ThreadSafeTest(); //實例化類對象 Thread tA = new Thread(t); // 以該類對象分別實例化4個線程 Thread tB = new Thread(t); Thread tC = new Thread(t); Thread tD = new Thread(t); tA.start(); // 分別啓動進程 tB.start(); tC.start(); tD.start(); } }
當咱們運行程序的時候,一個線程先開始工做,給num上了一把鎖,而後其餘三個線程就不能再訪問這個區域,等到tA執行完售票的操做將票數減1並輸出後,對象鎖被釋放,而後下一個線程又開始工做,再給num上了一把鎖,以此類推,直到票數爲0後結束進程。
能夠看出運行結果不正常,最後還有出現貨物有剩餘的狀況,這是由於Producer和customer的存取速度不同,致使二者不能很好的進行交互,從而使最後剩於貨物結果出現異常。
synchronized, wait, notify
解決該問題(關鍵代碼截圖,需出現學號)
運行結果:
運行結果:
學生 | 負責任務 |
---|---|
陳曉菲 | 圖書管理模塊 |
廖文姑 | 菜單類及測試類 |
賈海濤 | 用戶管理模塊 |
我負責的是圖書管理模塊,裏面包含兩個類,圖書館類和圖書類,用於進行書籍的管理。
圖書類:
//201621123031 public class Book { private String name; private long ID; private String category; public Book(String name,long ID,String category){ ………… } /* *get()和set()和方法 */
圖書館類:
public class Library { public enum LendOrBack{ //用於變動借書還書後的書籍變化 LEND,BACK } private static Map<Book,Integer> books=new TreeMap<Book,Integer>(); //用於存儲圖書信息及數量 static{ initializeBookStore(); } private static void initializeBookStore(){ Book book1 = new Book("紅與黑",111,"文學類"); Book book2 = new Book("平凡的世界",112,"文學類"); Book book3 = new Book("雙城記",113,"文學類"); Book book4 = new Book("資本論",114,"經濟類"); Book book5 = new Book("孫子兵法",115,"軍事類"); Book book6 = new Book("人間詞話",116,"藝術類"); Book book7 = new Book("詩經",117,"藝術類"); Book book8 = new Book("楚辭",118,"藝術類"); Book book9 = new Book("戰國策",119,"歷史類"); Book book10 = new Book("國家地理",120,"地理類"); books.put(book1, 30); books.put(book2, 50); books.put(book3, 40); books.put(book4, 10); books.put(book5, 20); books.put(book6, 15); books.put(book7, 35); books.put(book8, 40); books.put(book9, 5); books.put(book10, 10); } public static Book peekBook(long ID) { //根據ID獲取某本書籍的信息 Iterator<Map.Entry<Book, Integer>> m = books.entrySet().iterator(); while(m.hasNext()){ Map.Entry<Book, Integer> e = m.next(); if(e.getKey().getID()==ID&&e.getValue()>0) return e.getKey(); } return null; } public static ArrayList<Book> peekBooks(String name) { //根據書名獲取某本書籍的信息 ……………… } public static void add(Book book,int num){ //添加書籍 if(books.get(book)==null){ books.put(book, num); } else{ books.put(book, books.get(book)+num); } } public static void remove(Book book){ //移除書籍 books.remove(book); } public static void lendOrBack(Book book,LendOrBack action){ //進行借書還書操做時書籍數量的變動 switch(action) { case LEND:{ books.put(book, books.get(book)-1); break; } case BACK:{ books.put(book, books.get(book)+1); break; } } } public static void display(){ //展現圖書館的藏書 Iterator<Map.Entry<Book, Integer>> m = books.entrySet().iterator(); System.out.println(" 書名 \t\t\tID\t\t類別\t\t數量"); while(m.hasNext()){ Map.Entry<Book, Integer> e = m.next(); if(e.getValue()>0) System.out.println(e.getKey().toString()+"\t\t"+e.getValue()); } System.out.println(); } }
BlockingQueue
解決生產者消費者問題關鍵代碼截圖
答:BlockingQueue
是阻塞隊列,當隊列中沒有數據的狀況下,消費者線程會被自動阻塞,直到有數據進入隊列,而當隊列中填滿數據的時候,生產者的全部線程都會被自動阻塞,直到隊列中有空的位置,線程纔會被自動喚醒。所以它不須要使用wait、notify就能夠達到解決同步問題的方法,這樣的方法比wait、notify更簡單且更方便。
題目集:多線程
須要有兩張圖(1. 排名圖。2.PTA提交列表圖)
須要將每週的代碼統計狀況融合到一張表中。
周次 | 總代碼量 | 新增代碼量 | 總文件數 | 新增文件數 |
---|---|---|---|---|
2 | 607 | 607 | 15 | 15 |
3 | 1642 | 1035 | 33 | 18 |
5 | 2044 | 402 | 42 | 9 |
6 | 2874 | 830 | 57 | 15 |
7 | 3161 | 287 | 63 | 6 |
8 | 4299 | 1138 | 72 | 9 |
9 | 4831 | 532 | 81 | 9 |
10 | 5475 | 644 | 93 | 12 |
11 | 5958 | 483 | 102 | 9 |
12 | 6819 | 861 | 116 | 14 |
觀看相關調試視頻
使用eclipse調試的步驟:
F5:單步執行程序,遇到方法時進入。在碰到方法內部出現問題的時候,就要用F5去深刻方法內部來進行調試。
F6:單步執行程序,遇到方法時跳過。在不用理會深層操做的時候使用F6。
F7:單步執行程序,從當前方法跳出。當進入某個方法內部想跳出來時使用F7。