孙星

20169221 2016-2017-2 《移动平台应用与开发》第五周学习总结

第十六章 输入输出

文件系统和路径

文件系统包含3种类型的对象:文件、目录、符号链接
FileSystem表示一个文件系统是一个抽象类,静态方法getDefault返回当前文件系统

FileSystem fileSystem=FileSystems.getDefault();

文件目录和处理的操作

1.创建和删除文件和目录
删除文件时,如果path是一个目录,目录必须为空,如果是一个符号链接,只有链接会被删除,并且没有连接目标,如果path不存在则会抛出一个NoSsuchFileException
2.复制和移动文件夹
CopyOption是java。nio.file中的一个接口
ATOMIC_MOVE:移动文件作为一个基本的文件系统操作
COPY_ATTRIBUTES:将属性复制到新的文件夹
REPLACE_EXISTING:

输入/输出流

java.io包中的四个抽象类

  • Reader
  • Writer
  • InputStream
  • OutStream
    流的好处是不管什么数据源和目标都可以使用。
    操作顺序:1)创建一个流。2)执行读取写入操作。3)调用流的close方法来关闭流。

读写二进制数据

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对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
1、通过实现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();方法,该方法执行完成后,线程就消亡了。
2、与方法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();

3、通过继承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多线程 -- 线程的优先级](http://silentlakeside.iteye.com/blog/1175981)
 
## 停止线程
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

HTTP Response Example Welcome to Brainy Software ``` ## 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,可以让它在服务器套接字监听端口上等待对绑定地址的一个乳香连接请求 #遇到的问题 1. ``` 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中常见的输入输出流案例学习](http://www.android100.org/html/201512/24/207000.html)
[JAVA多线程与并发学习总结分析](http://blog.csdn.net/brandohero/article/details/42915761)
#代码提交截图
![](http://images2015.cnblogs.com/blog/1115797/201704/1115797-20170402161218008-974296222.png)
##上周考试错题总结
![](http://images2015.cnblogs.com/blog/1115797/201704/1115797-20170402161658617-2068364925.png)
![](http://images2015.cnblogs.com/blog/1115797/201704/1115797-20170402161646945-1326668934.png)
![](http://images2015.cnblogs.com/blog/1115797/201704/1115797-20170402161722508-1033973125.png)
##博客评论
[唐瑶](http://www.cnblogs.com/littletang/p/6627733.html)5分
[姚静](http://www.cnblogs.com/yaojingjing/p/6649221.html)5分
##学习进度条
|          |教材学习      |视频学习        |博客量(新增/累积)|重要成长                                     |
|:--------:|:-----------:|:-------------:|:--------------:|-------------------------------------------|
|目标       |16 19 22章    |               |20篇            |                                            |
|第五周     |第16 19 22章  |《Linux基础入门》|1/1             |学习输入输出线程和网络                    |
|           |              |                 |2/3             |                                          |

posted on 2017-03-27 23:26  20169221孙星  阅读(253)  评论(7编辑  收藏  举报

导航