20169221 2016-2017-2 《移動平臺應用與開發》第五週學習總結

第十六章 輸入輸出

文件系統和路徑

文件系統包含3種類型的對象:文件、目錄、符號連接
FileSystem表示一個文件系統是一個抽象類,靜態方法getDefault返回當前文件系統html

FileSystem fileSystem=FileSystems.getDefault();

文件目錄和處理的操做

1.建立和刪除文件和目錄
刪除文件時,若是path是一個目錄,目錄必須爲空,若是是一個符號連接,只有連接會被刪除,而且沒有鏈接目標,若是path不存在則會拋出一個NoSsuchFileException
2.複製和移動文件夾
CopyOption是java。nio.file中的一個接口
ATOMIC_MOVE:移動文件做爲一個基本的文件系統操做
COPY_ATTRIBUTES:將屬性複製到新的文件夾
REPLACE_EXISTING:java

輸入/輸出流

java.io包中的四個抽象類android

  • Reader
  • Writer
  • InputStream
  • OutStream
    流的好處是無論什麼數據源和目標均可以使用。
    操做順序:1)建立一個流。2)執行讀取寫入操做。3)調用流的close方法來關閉流。web

    讀寫二進制數據

    1.讀二進制數據
    InputStream能夠從池中讀取一個二進制數據。
    因爲File.newInputStream沒有緩存,可使用BufferedInputStream包裝以達到更好的性能。
Path path = ...
try (InputStream inputStream = Files.newInputStream(path,
StandardOpenOption.READ;
BufferedInputStream buffered =
new BufferedInputStream(inputStream)) {
// manipulate buffered, not inputStream
} catch (IOException e) {
// do something with e
}

Input類使用一個內部指針,指向讀取數據開始的位置。每個重載的read方法都有返回所讀取的字節數,若是沒有數據讀入到InputStream,返回-1.
2.寫二進制數據
OutputStream將二進制數據寫入池中一個流。
因爲File.newOutputStream沒有緩存,可使用BufferedOutputStream包裝以達到更好的性能數據庫

Path path = ...
try (OutputStream outputStream = Files.newOututStream(path,
StandardOpenOption.CREATE, StandardOpenOption.APPEND;
BufferedOutputStream buffered =
new BufferedOutputStream(outputStream)) {
// manipulate buffered, not outputStream
} catch (IOException e) {
// do something with e
}

寫文本

1.Write和OutputStream相似,不過它出路的是字符而不是字節
2.OutStreamWriter:是字符流和字節流之間的橋樑,可以將Unicode轉化爲byte表示。瀏覽器

OutputStream os = Files.newOutputStream(path, openOption);
OutputStreamWriter writer = new OutputStreamWriter(os, charset);

3.PrintWriter容許經過給其構造方法傳入編碼信息,它更易使用,由於它添加了9種重載方式能夠打印任意類型的java基本類型和對象。
可使用bufferwriter將一個write包裝起來以獲得更好的性能,可是bufferwriter不能這麼包裝。緩存

PrintWriter printWriter = ...;
BufferedWriter bw = new BufferedWriter(printWriter);

讀文本

1.Reader:讀取字符的輸入流
2.InputStreamReader:讀取字節,並使用指定字符集將其轉換爲字符。
3.BufferedReader:包裝另外一個Reader,並提供一個緩存。提取一個readLine方法來讀取一行文本。服務器

隨機訪問文件

1.對於 FileInputStream/FileOutputStream、FileReader/FileWriter 來講,它們的實例都是順序訪問流,即只能進行順序讀/寫。而類 RandomAccessFile 則容許文件內容同時完成讀和寫操做,它直接繼承 object,而且同時實現了接口 DataInput 和 DataOutput,提供了支持隨機文件操做的方法:
readXXX()或者 writeXXX():如 ReadInt(),ReadLine(),WriteChar(),WriteDouble()等
int skipBytes(int n):將指針向下移動若干字節
length():返回文件長度
long getFilePointer():返回指針當前位置
void seek(long pos):將指針調用所需位置網絡

對象序列化

ObjectOutputStream:建立一個ObjectOutputStream類以後能夠序列化對象和基本類型。多線程

public void writeBoolean(boolean value)
public void writeByte(int value)
public void writeBytes(String value)
public void writeChar(int value)
public void writeChars(String value)
public void writeDouble(double value)
public void writeFloat(float value)
public void writeInt(int value)
public void writeLong(long value)
public void writeShort(short value)
public void writeObject(java.lang.Object value)

若是一個序列化對象包含其餘的對象,被包含對象必須實現Serializable。這樣被包含對象纔是可序列化的。
對象序列化是一個先進後出的方法,先序列化的對象,必須是最後解序列化的

第十九章 線程

線程

線程是一個基本處理單元操做系統分配和處理的時間就是按照線程來勁心儀的。在一個進程中能夠有多個線程執行代碼,現成有時候也叫做一個輕量級進程,或者叫作一個執行環境。

建立一個線程

(1)Callable規定的方法是call(),Runnable規定的方法是run().
(2)Callable的任務執行後可返回值,而Runnable的任務是不能返回值得
(3)call方法能夠拋出異常,run方法不能夠
(4)運行Callable任務能夠拿到一個Future對象,表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並檢索計算的結果。經過Future對象能夠了解任務執行狀況,可取消任務的執行,還可獲取執行結果。
一、經過實現Runnable接口來建立Thread線程:
  步驟1:建立實現Runnable接口的類:

  class SomeRunnable implements Runnable
  {
  public void run()
  {
  //do something here
  }
  }

  步驟2:建立一個類對象:

  Runnable oneRunnable = new SomeRunnable();

  步驟3:由Runnable建立一個Thread對象:

  Thread oneThread = new Thread(oneRunnable);

  步驟4:啓動線程:
  oneThread.start(); 
註釋:線程的執行流程很簡單,當執行代碼oneThread.start();時,就會執行oneRunnable對象中的void run();方法,該方法執行完成後,線程就消亡了。
二、與方法1相似,經過實現Callable接口來建立Thread線程:其中,Callable接口(也只有一個方法)定義以下:

  public interface Callable
  {
  V call() throws Exception;
  }

  步驟1:建立實現Callable接口的類SomeCallable(略);
  步驟2:建立一個類對象:

  Callable oneCallable = new SomeCallable();

  步驟3:由Callable建立一個FutureTask對象:

  FutureTask oneTask = new FutureTask(oneCallable);

註釋:FutureTask是一個包裝器,它經過接受Callable來建立,它同時實現了Future和Runnable接口。
  步驟4:由FutureTask建立一個Thread對象:
   Thread oneThread = new Thread(oneTask); 
 步驟5:啓動線程:

  oneThread.start();

三、經過繼承Thread類來建立一個線程:
  步驟1:定義一個繼承Thread類的子類:

  class SomeThead extends Thraad
  {
  public void run()
  {
  //do something here
  }
  }

  步驟2:構造子類的一個對象:
  SomeThread oneThread = new SomeThread(); 
  步驟3:啓動線程

使用多線程

咱們可使用多線程.

package app19;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ThreadDemo3 extends JFrame {
JLabel countUpLabel = new JLabel("Count Up");
JLabel countDownLabel = new JLabel("Count Down");
class CountUpThread extends Thread {
public void run() {
int count = 1000;
while (true) {
try {
sleep(100);
} catch (InterruptedException e) {
}
if (count == 0)
count = 1000;
countUpLabel.setText(Integer.toString(count--));
}
}
}
class CountDownThread extends Thread {
public void run() {
int count = 0;
while (true) {
try {
sleep(50);
} catch (InterruptedException e) {
}
if (count == 1000)
count = 0;
countDownLabel.setText(Integer.toString(count++));
}
}
}
public ThreadDemo3(String title) {
super(title);
init();
}
private void init() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().setLayout(new FlowLayout());
this.add(countUpLabel);
this.add(countDownLabel);
this.pack();
this.setVisible(true);
new CountUpThread().start();
new CountDownThread().start();
}
private static void constructGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
ThreadDemo3 frame = new ThreadDemo3("Thread Demo 3");
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
constructGUI();
}
};
}
}

線程優先級

若是在應用程序中有多個程序在運行,但一些線程比另外一些重要於是須要分配更多的CPU時間的狀況下,能夠在一個進行中爲不一樣的線程指定不一樣的優先級。通常狀況下,若是有優先級較高的線程在工做,就不會給優先級較低的線程分配任什麼時候間片,其優勢是能夠保證給接收用戶輸入的線程指定較高的優先級。在大多數的時間內,這個線程什麼也不作。而其餘線程則執行它的任務。可是,若是用戶輸入了信息,這個線程就會當即得到比應用程序中其餘線程更高的優先級,在短期內處理用戶輸入數據。
設置進程優先級要使用

public final void setPriority(int priority)

線程的優先級及其含義
Highest
將線程安排在具備任何其餘優先級的線程以前
AboveNormal
將線程安排在具備Highest優先級的線程以後,在具備Normal優先級的線程以前
Normal
將線程安排在具備AboveNormal優先級的線程以後,在具備BelowNormal優先級的線程以前。默認狀況下,線程具備Normal優先級
BelowNormal
將線程安排在具備Normal優先級的線程以後,在具備Lowest優先級的線程以前
Lowest
將線程安排在具備任何其餘優先級的線程以後
__Java多線程 -- 線程的優先級

中止線程

Thread有一個stop的方法來中止一個線程。中止一個線程時候應該讓run方法天然退出,直接讓條件計算爲假便可。

boolean condition = true;
public void run {
while (condition) {
// do something here
}
}
In your class, you also need to provide a method to change the value of condition.
public synchronized void stopThread() {
condition = false;
}

同步

使用線程的一個重要內容是同步訪問多個線程訪問的任何變量。所謂同步,是指在某一時刻只有一個線程能夠訪問變量。若是不能確保對變量的訪問是同步的,就可能會產生錯誤或不可預料的結果。通常狀況下,當一個線程寫入一個變量,同時有其餘線程讀取或寫入這個變量時,就應同步變量。經過指定對象的加鎖和解鎖能夠同步代碼段的訪問。在.NET的System.Threading命名空間中提供了Monitor類來實現加鎖與解鎖。這個類中的方法都是靜態的,因此不須要實例化這個類。下表中一些靜態方法提供了一種機制用來向同步對象的訪問從而避免死鎖和維護數據一致性。
1.線程干擾:假設一個線程讀取了userCount的值並增長它,在它有機會將增長後的值存儲回去以前,另外一個線程讀取它並獲得了舊的值。當第二個線程最終獲得機會寫userCount時,他會替代第一個線程增長後的值。結果,userCount並無反映西湖正確的用戶數目,一個事件有兩個非原子性操做在不一樣線程中進行。
2.原子操做:組合起來可讓系統其餘部分將其當作一個單個操做的一組操做,不會用法線程干擾
3.方法同步:Jav對象都有一個內在的鎖。獲取一個對象內在的鎖是一種獨佔是的訪問一個對象的方法。試圖訪問一個度一項線程將會被阻塞,直到持有鎖的線程釋放該鎖。
當線程執行到synchronized的時候,若是得不到鎖標記,這個線程會被加入到一個與該對象的鎖標記相關連的等待線程池當中,等待鎖標記。當線程執行完同步代碼,就會釋放鎖標記。一個剛釋放了鎖標記的線程能夠立刻再次得到鎖標記,當同步塊遇到break或拋出exception時,線程也會釋放鎖標記。
4.塊同步:同步塊給了你一個對象的內在鎖在塊中代碼執行以後釋放該鎖。

線程協調

當方法體或代碼塊被synchronized方法修飾時,有一個線程在執行這部分代碼時,其它線程沒法同時執行這部分代碼。在Java中,有三個方法能夠對線程進行主動高效的控制,它們是wait,notify和notifyAll。wait是主動讓線程等待的方法,而notify和notifyAll則是激活等待中的線程的方法。他們都是Object類的方法,也就是說任何對象均可以使用這三個方法。
1) wait,notify和notifyAll都是java.lang.Object的方法,它們用來對線程進行調度.
2) obj.wait()是把執行這句的線程放入obj的wait set中.
3) obj.notify()是從wait set中喚醒一個線程,這個線程在當前線程釋放對obj的鎖定後即獲取這個鎖定.
4) obj.notifyAll()是喚醒全部在obj的wait set中的線程,這批線程在當前線程釋放obj的鎖定後去競爭這個鎖定,最終只有一個能得到,其它的又從新返回wait set等待下一次激活.
5) 執行這個wait,notify和notifyAll這三個方法前,當前線程(即執行obj.wait(), obj.notify()和obj.notifyAll()代碼的線程)必須持有obj的鎖定.

第二十二章 網絡

超文本傳輸協議

HTTP是容許Web服務器和瀏覽器之間經過互聯網發送和接收數據的協議。
1.HTTP請求:一次HTTP請求包括方法、請求頭和請求實體

POST /examples/default.jsp HTTP/1.1
Accept: text/plain; text/html
Accept-Language: en-gb
Connection: Keep-Alive
Host: localhost
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US;
rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6
Content-Length: 33
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
lastName=Franks&firstName=Michael

2.HTTP響應:包括三部分協議-狀態碼-說明、響應頭、響應實體。

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Date: Thu, 12 Aug 2010 13:13:33 GMT
Content-Type: text/html
Last-Modified: Thu, 5 Aug 2010 13:13:12 GMT
Content-Length: 112
<html>
<head>
<title>HTTP Response Example</title>
</head>
<body>
Welcome to Brainy Software
</body>
</html>

java.net.URL

1.URL是互聯網資源惟一的地址,它是指向互聯網「資源」的指針。資源能夠是簡單的文件或目錄,也能夠是對更爲複雜的對象的引用,例如對數據庫或搜索引擎的查詢。 簡單的能夠把URL理解爲包含:協議、主機名、端口、路徑、查詢字符串和參數等對象。每一段能夠獨立設置。
相對 URL 不須要指定 URL 的全部組成部分。若是缺乏協議、主機名稱或端口號,這些值將從完整指定的 URL 中繼承。
調用URL類來構建URL

public URL(java.lang.String spec)
public URL(java.lang.String protocol, java.lang.String host,
java.lang.String file)
public URL(java.lang.String protocol, java.lang.String host,
int port, java.lang.String file)
public URL(URL context, String spec)

2.解析URL

public java.lang.String getFile()
public java.lang.String getHost()
public java.lang.String getPath()
public int getPort()
public java.lang.String getProtocol()
public java.lang.String getQuery()

3.讀取web資源

public final java.io.InputStream openStream()
throws java.io.IOException

java.net.URLConnection

1.讀取web資源
2.寫一個到web服務器
在請求發送以前,HttpURLConnetion會把全部須要發送的數據放到緩衝區裏,無論你是否使用connection.setRequestProperty(「Content-Length」, contentLength);設置contentLength,當你並行發送大量的POST請求時,這可能會引發OutOfMemoryExceptions 異常,爲了不這個問題,你須要使HttpURLConnection.setFixedLengthStreamingMode()方法。可是若是不能事先知道內容的長度,可使用HttpURLConnection.setChunkedStreamingMode()方法設置爲塊狀流模式。在塊狀流模式的狀況下,放在塊裏的內容將會被強行發送出去。下邊的例子將會把發送的內容按照每塊1KB的大小發送出去。

java.net.Scoket

套接字是的應用程序可以從網絡打野去呀或者從網絡寫入信息。
成功喜歡簡Socket類一個實例後可使用它發送或者接受字節流

java.net.SeverScoket

Socket是一個「客戶端」套接字,想要實現一個女遠程服務,須要使用java.net.ServerSocket類。他是服務器套接字的一個實現
構造方法

public ServerSocket(int port, int backLog,
InetAddress bindingAddress);

有了ServerSocket,可讓它在服務器套接字監聽端口上等待對綁定地址的一個乳香鏈接請求

遇到的問題

class First extends Thread
{
    public First()
    {
        start();
    }
     
    synchronized public void run()
    {
        try
        {
            wait();
        }
        catch(InterruptedException e)
        {
            e.printStackTrace();
        }
        try
        {
            sleep(2000);
        }
        catch(InterruptedException e)
        {
            e.printStackTrace();
        }
        System.out.println("hello world~");
    }
}
class Second extends Thread
{
    First first;
    public Second(First first)
    {
        this.first = first;
        start();
    }
     
    synchronized public void run()
    {
        try
        {
            wait();
        }
        catch (InterruptedException e1)
        {
            e1.printStackTrace();
        }
        synchronized( first )
        {
            try
            {
                sleep(2000);
                System.out.println("I'm faster than first~");
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            first.notifyAll();
        }
    }
}
public class Main
{
    public static void main(String[] args) throws InterruptedException
    {
        First first = new First();
        Second second = new Second(first);
        synchronized( second )
        {
            System.out.println("I'm faster than second~");
            second.notifyAll();
        }
    }
}

問題:輸出只有I'm faster than second~
緣由:在main函數中,對second.notifyAll()的調用早於second中的wait()調用(由於是多線程並行,故函數響應時間與代碼前後順序無關),這樣先喚醒了second,緊接着second纔開始wait,所以就處於無響應狀態。
解決方法:只要在second.notifyAll()調用以前空出一點時間先讓second的wait調用開始便可,事實上,這段時間如此之短以致於在我電腦上只須要在以前加一行輸出語句便可。爲了保險起見,仍是多加了個sleep
2.HTTP響應狀態爲4xx(客戶端錯誤)或者5xx(服務器錯誤)
解決方法:你能夠經過HttpUrlConnection.getErrorStream()來查看服務器發送過來的信息。

參考資料

java中常見的輸入輸出流案例學習
JAVA多線程與併發學習總結分析

代碼提交截圖

上週考試錯題總結



博客評論

唐瑤5分
姚靜5分

學習進度條

教材學習 視頻學習 博客量(新增/累積) 重要成長
目標 16 19 22章 20篇
第五週 第16 19 22章 《Linux基礎入門》 1/1 學習輸入輸出線程和網絡
2/3
相關文章
相關標籤/搜索