《Java程序设计》第6周学习总结

20145333 《Java程序设计》第6周学习总结

教材学习内容总结

输入和输出

  • 串流设计概念

要想活用输入/输出API,一定先要了解Java中如何以串流抽象化输入/输出概念,以及InputStream,OutputStream继承架构。如此一来,无论标准输入/输出,文档输入/输出,网络输入/输出,数据库输入/输出,都可以用一致的操作进行处理。
从应用程序来看,如果要将数据从来源取出,可以使用输入串流:如果要将数据写入目的地,可以使用输出串流,在Java中,输入串流代表对象为java.io.InputStream实例,输出串流代表对象为java.io.OutputStream实例,无论数据源或目的地为何,只要设法取得InputStream或OutputStream的实例,接下来操作输入/输出的方式是一致的,无须理会来源或目的地的真正形态。

package Stream;
import java.io.*;
public class IO {
public static void dump(InputStream src, OutputStream dest)
        throws IOException {
    try (InputStream input = src; OutputStream output = dest) {
        byte[] data = new byte[1024];
        int length;
        while ((length = input.read(data)) != -1) {
            output.write(data, 0, length);
        }
    }
}
}
  • 串流继承架构

System.in与System.out分别是InputStream和OutputStream的实例。
可以使用System的setIn()方法指定InputStream实例,重新指定标准输入来源。
ByteArrayInputStream是InputStream的子类,可以指定byte数组创建实例,一旦创建就将byte数组当作数据源进行读取,同理,ByteArrayOutputStream将byte数组当作目的地写出数据。

  • 串流处理装饰器

串流装饰器本身并没有改变InputStream和OutputStream的行为,只是在得到数据之后,再做一些加工处理。
·BufferedInputStream与BufferedOutputStream主要在内部提供缓冲区功能。

package Stream;
import java.io.*;
public class BUfferedIO {
public static void dump(InputStream src, OutputStream dest)
        throws IOException {
    try(InputStream input = new BufferedInputStream(src);
        OutputStream output = new BufferedOutputStream(dest)) {
        byte[] data = new byte[1024];
        int length;
        while ((length = input.read(data)) != -1) {
            output.write(data, 0, length);
        }
    }
}
}

·DataInputStream与DataOutputStream主要提供读取、写入java基本数据类型的方法,会自动在指定的类型与字节之间转换。

package Stream;

import java.io.IOException;
import static java.lang.System.out;

public class MemberDemo {
public static void main(String[] args) throws IOException {
    Member[] members = {
            new Member("B1234", "Justin", 90),
            new Member("B5678", "Monica", 95),
            new Member("B9876", "Irene", 88)
    };
    for(Member member : members) {
        member.save();
    }
    out.println(Member.load("B1234"));
    out.println(Member.load("B5678"));
    out.println(Member.load("B9876"));
}
}
  • 字符处理装饰器

如果串流处理的字节数据,实际上代表某些字符的编码数据,而你想要将这些字节数据转换为对应的编码字符,可以使用InputStreamReader、OutputStreamWriter对串流数据打包,在建立InputStreamReader与OutputStreamWriter时,可以指定编码,如果没有指定编码,则以JVM启动时所获取的默认编码来做字符转换。PrintStream与PrintWriter使用上极为相似,不过除了可以对OutputStream打包之外,PrintWriter还可以对Writer进行打包,提供print()、println()、format()等方法。

线程与并行API

  • 线程

在java中,如果想在main()以外独立设计流程,可以撰写类操作java.lang.Runnable接口,流程的进入点是操作在run()方法中。
在java中,从main()开始的流程会由主线程执行,可以创建Thread实例来执行Runnable实例定义的run()方法。

  • 等待与通知

wait()、notify()、notifyAll()是object定义的方法,可以通过这3个方法控制线程释放对象的锁定,或者通知线程参与锁定竞争。若调用锁定对象的wait()方法,线程会释放对象锁定,并进入对象等待集合从而处于阻断状态,其他线程可以竞争对象锁定,取得锁定的线程可以执行synchronized范围的程序代码。放在等待集合的线程不会参与CPU排班,wait()可以指定等待时间,时间到之后线程会再次加入排班。如果指定时间0或不指定,则线程会持续等待,直到被中断(调用interrupt())或是告知(notify())可以参与排班。

  • 并行API

Lock 接口主要操作类之一为 ReentrantLock,可以达到synchronized 的作用,也提供额外的功能,例:
package cc.openhome;

import java.util.Arrays;
import java.util.concurrent.locks.*;

public class ArrayList<E> {
private Lock lock = new ReentrantLock();
private Object[] elems;
private int next;

public ArrayList(int capacity) {
    elems = new Object[capacity];
}

public ArrayList() {
    this(16);
}

public void add(E elem) {
    lock.lock();
    try {
        if (next == elems.length) {
            elems = Arrays.copyOf(elems, elems.length * 2);
        }
        elems[next++] = elem;
    } finally {
        lock.unlock();
    }
}

public E get(int index) {
    lock.lock();
    try {
        return (E) elems[index];
    } finally {
        lock.unlock();
    }
}

public int size() {
    lock.lock();
    try {
        return next;
    } finally {
        lock.unlock();
    }
}
}
  • 使用ReadWriteLock

ReadWriteLock接口定义了读取锁定与写入锁定行为,可以使用readLock()、writeLock()方法返回Lock操作对象。ReentrantReadWriteLock是ReadWriteLock接口的主要操作类,readLock()方法会返回ReentrantReadWriteLock.ReadLock实例,writeLock()犯法会返回ReentrantReadWriteLock.WriteLock实例。

  • 使用StampedLock

StampedLock类可支持了乐观读取操作。也就是若读取线程很多,写入线程很少的情况下,你可以乐观地认为,写入与读取同时发生的机会很少,因此不悲观的使用哇暖的读取锁定,程序可以查看数据读取之后,是否遭到写入线程的变更,再采取后续的措施。

  • 使用Condition

Condition接口用来搭配Lock,最基本用法就是达到Object的wait()、notify()、notifyAll()方法的作用。Condition的await()、signal()、signalAll()方法,可视为Object的wait()、notify()、notifyAll()方法的对应。

教材学习中的问题和解决过程

  1. 撰写单线程序、多线程程序的方式差别:操作Runnable接口的好处就是较有弹性,类还有机会继承其他类;若继承了Thread类,那该类就是一种Thread,通常是为了直接利用Thread中定义的一些方法,才会继承Thread来操作。
  2. InputStream、Reader与Writer区别:
    Writer针对于字符数据写入,Reader针对于字符数据的读取,InputStream针对于串流输入

本周代码托管截图

地址http://git.oschina.net/20145333/java-besti-is-2015-2016-2-20145333/tree/master

其他(感悟、思考等,可选)

每周的学习都有新的体会,随着学习的不断深入,学习内容中出现了越来越多新的概念,也对以前的内容有了更深的理解。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 3500行 15篇 400小时
第一周 100/100 2/2 20/20
第二周 150/250 1/3 18/38
第三周 100/350 1/4 22/60
第四周 300/650 1/5 30/90
第五周 100/750 1/6 20/110
第六周 350/1100 1/7 25/135

posted on 2016-04-10 17:46  20145333茹翔  阅读(143)  评论(1编辑  收藏  举报

导航