20145233韩昊辰 第六周总结

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

教材学习内容总结

一、输入/输出

1.InputStream与OutputStream

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

2.串流继承架构

还记得System.in与System.out吗?查看API文件的话,会发现它们分别是InputStream与PrintStream的实例,分别代表标准输入与标准输出,以个人计算机而言,通常对应至文本模式中的输入与输出。可以使用System的setIn()方法指定InputStream实例,重新指定标准输入来源。

3.串流处理装饰器

InputStream、OutputStream提供串流基本操作,如果想要为输入/输出的数据做加工处理,则可以使用打包器类。前面示范过的Scanner类就是作为打包器,其接受InputStream实例,你操作Scanner打包器相关方法,Scanner会实际操作打包的InputStream取得数据,并转换为你想要的数据类型。InputStream、OutputStream的一些子类也具有打包器的作用。前面介绍的PrintStream就是实际例子,你操作PrintStream的print()、println()等方法,PrintStream会自动转换为byte数组数据,利用打包的OutputStream进行输出。下面介绍几种常用的串流装饰器类。

第一种是BufferedInputStream与BufferedOutputStream,两者都具备缓冲作用。如果InputStream第一次read()时可以尽量读取足够的数据至内存的缓冲区,后续调用read()时先看看缓冲区是不是还有数据,如果有就从缓冲区读取,没有再从来源读取数据至缓冲区,这样减少从来源直接读取数据的次数,对读取效率将会有帮助。毕竟内存的访问速度较快。如果OutputStream每次write()时可将数据写入内存中的缓冲区,缓冲区满了再将缓冲区的数据写入目的地,这样可减少对目的地的写入次数,对写入效率也会有帮助。

第二种是DataInputStream与DataOutputStream,DataInputStream与DataOutputStream提供读取、写入Java基本数据类型的方法,像是读写int、double、boolean等的方法。这些方法会自动在指定的类型与字节间转换。

第三种是ObjectInputStream与ObjectOutputStream,ObjectInputStream与ObjectOutputStream可以将内存中的对象整个储存下来,之后再读入还原为对象。ObjectInputStream提供readObject()方法将数据读入为对象,而ObjectOutputStream提供writeObject()方法将对象写至目的地,可以被这两个方法处理的对象,必须操作java.io.Serializable接口,这个接口并没有定义任何方法,只是作为标示之用,表示这个对象是可以串行化的。如果在做对象串行化时,对象中某些数据成员不希望被写出,则可以标上transient关键字。

4.字符处理装饰器

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

二、线程与并行API

1.线程

到目前为止介绍过的各种范例都是单线程程序,也就是启动的程序从main()程序进入点开始至结束只有一个流程。有时候还需要设计程序可以拥有多个程序,也就是所谓的多线程程序。
要让目前的流程暂停时间,可以使用java.lang.Thread的静态sleep()方法,指定的单位是毫秒,调用这个方法必须处理java.lang.InterruptedException
如果想在main()之外独立设计流程,可以撰写java.lang.Runnable接口,流程的进入点是操作run()方法。从main()开始的流程会由主程序执行,可以创建Thread实例来执行Runnable实例定义的rin()方法,要启动线程执行指定的线程,必须调用Thread实例的start()方法。
如果主线程中启动了额外线程,默认会等待被启动的所有线程都执行完run()方法才终止JVM,如果一个Thread被标示为Daemon线程,在所有的非Daemon线程都结束时,JVM就会终止。
每个线程都属于某个线程群组,如果没有指定,则归入产生该子线程的线程群组,也可以自行指定线程群组,线程一旦归入某个群组,就无法再更换。ThreadGroup的某些方法,可以对群组中所有线程产生作用。如果想要一次取得群组中所有线程,可以使用enumerate()方法。activeCount()方法取得群组的线程数量。

2.等待与通知

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

3.并行API

使用Thread建立多线程程序,必须亲自处理synchornized、对象锁定、wait()、notify()、notifyAll()等细节,如果需要的是线程池、读写解锁高等级操作,从JDK5之后提供了java.util.concurrent,可基于其中的API建立更稳固的并行应用程序。
并行API可以分为以下几个类,书上有定义,我就不再陈述了。
1.Lock、ReadWriter与Condition
2.使用Executor
3.并行Collection简介
这里是书上龟兔赛跑的例子:

这里有个问题我在下面提出。
第二个例子关于等待与通知的:

public class ProducerConsumerDemo {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();
        new Thread(new Producer(clerk)).start();
        new Thread(new Consumer(clerk)).start();
    }
}

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

这两章的内容还是比较多的,并且有很多新的东西,但是在理解方面,并没有前面的概念性的知识难理解,在将书上的代码敲过一些之后,对于这些内容就有了很好地理解, 只是书上的知识点还是蛮多的,这就需要我们花费大量的时间去理解,

代码调试中的问题和解决过程

在327页的代码中,虽然程序可以执行,但是出现的问题却是,每次都是乌龟先跑完,兔子总是在乌龟跑完之后才走。

import static java.lang.System.out;

public class TortoiseHareRace {
    public static void main(String[] args) {
        boolean[] flags = {true, false};
        int totalStep = 10;
        int tortoiseStep = 0;
        int hareStep = 0;
        out.println("龜兔賽跑開始...");
        while(tortoiseStep < totalStep && hareStep < totalStep) {
            tortoiseStep++;
            out.printf("烏龜跑了 %d 步...%n", tortoiseStep);
            boolean isHareSleep = flags[((int) (Math.random() * 10)) % 2];
            if(isHareSleep) {
                out.println("兔子睡著了zzzz");
            } else {
                hareStep += 2;
                out.printf("兔子跑了 %d 步...%n", hareStep);
            }
        }
    }
}

这是运行的结果,我还在思考这个问题,我觉得应该还是代码中的问题。

本周代码托管截图


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

在这一周的学习里,有了第一次的Java实验,虽说是第一次实验,但是我也在其中学到了很多东西,比如如何设立断点之类的,还有在其中自己编写的代码总是漏洞百出,一直在参照书上的不停地修改代码,最终可以跑起来程序,这个感觉真的是很棒的,虽然在这个代码中还有一些小的瑕疵,但是我还在修改,相信不久之后不但这个代码可以完美运行,我的编程技术也会有很大提升。
在这周后面两章的学中,学会了更多的知识,在第十章中学到了输入串流以及字符处理等很多新的功能,并且在第十一章里接触了新的知识----线程,也制作了龟兔赛跑的游戏程序,这都很有意思,我现在真的觉得学会一门新的语言并且可以加以运用是多么有意思。
只是这周的实验很多,总共有四个实验,所以这周协调时间显得尤为重要,这也就需要我在平时学习的时候安排好自己的时间,也需要自己对这些任务作出规划,真的是充实的一周,虽然累,但是学到了很多东西。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 4000行 24篇 350小时
第一周 150/150 2/2 15/15
第二周 200/350 2/4 20/35
第三周 350/700 2/6 30/65
第四周 500/1200 1/7 35/100
第五周 1100/2300 1/8 30/130
第六周 1000/3300 1/9 30/160
posted @ 2016-04-10 15:17  20145233韩昊辰  阅读(140)  评论(1编辑  收藏  举报