您的位置:首页 > 编程语言 > Java开发

20145232 韩文浩 《Java程序设计》第6周学习总结

2016-04-10 18:54 441 查看

教材学习内容总结

Java是以串流(Stream)的方式来处理输入与输出。

串流是一种抽象观念,从键盘输入资料,将处理结果输入档案,以及读取档案的内容等动作皆视为串流的处理。

输入串流代表对象为
java.io.InputStream
实例,输出串流代表对象
java.io.OutputStream
实例。

在不使用InputStream与OutputStream时,必须使用
close()
方法关闭串流。

System.in与System.out分别是InputStream与PrintStream的实例,标准输入与标准输出。

FileInputStream是InputStream的子类,可以指定文件名创建实例,一旦创建文档就开启,接着就可以用来读取数据,FileOutputStream是OutputStream的子类,可以指定文件名创建实例,一旦创建文档就开启,接着就可以用来写出数据,无论FileInputStream还是FileOutputStream,不使用时都要用
close()
关闭文档。

在启用JVM时,可以指定-Dfile.encoding来指定FileReader、FileWriter所使用的编码

> java -Dfile.encoding=UTF-8 cc.openhome.CharUtil sample.txt


BufferedInputStream与BufferedOutputStream提供的是前面描述的缓冲区功能。

ByteArrayInputStream是InputStream的子类,可指定byte数组创建实例。一旦创建就可以将byte数组当作数据源进行读取。ByteArrayOutputStream是OutputStream的子类,可指定byte数组创建实例。一旦创建就可以将byte数组当作目的地写出数据。

字符数据的读取,java SE提供了java.io.reader类。

字符数据的写入则提供了java.io.writer类。

使用InputStreamReader和OutputstreamWriter可对串流数据打包。

在java中,如果想在main()以外独立设计流程,可以撰写类操作java.lang.Runnable接口,流程的进入点是操作在run()方法中。

撰写多线程程序的方式:将流程定义在Runnable的run()方法中 / 继承Thread类,重新定义run()方法

在java中,从main()开始的流程会由主线程执行,可以创建Thread实例来执行Runnable实例定义的run()方法。

Thread与Runnable:从抽象观点与开发者的角度来看,JVM是台虚拟计算机,只安装了一颗称为主线程的CPU,可执行main()定义的执行流程。如果想要为JVM加装CPU,就是创建Thread实例,要启动额外CPU就是调用Thread实例的start()方法,额外CPU执行流程的进入点,可以定义在Runnable接口的run()方法中。除了将流程定义在Runnable的run()方法中,另一个撰写多线程程序的方式,就是继承Thread类,重新定义run()方法。操作Runnable接口的好处就是较有弹性,你的类还有机会继承其他类。若继承了Thread,那该类就是一种Thread,通常是为了直接利用Thread中定义的一些方法,才会继承Thread来操作。

要让目前流程暂停指定时间,可以使用java.lang.Thread的静态sleep()方法。

在调用Thread实例start()方法后,基本状态为可执行,被阻断,执行中。

thread类上定义有stop()方法,被标示为Deprecated。

每个线程都属于某个线程群组。在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口。

每个对象都会有个内部锁定,称为监控锁定。

lock接口主要操作类之一为ReentrantLock,可以达到synchronized的作用。

为了避免调用Lock()后,在后续执行流程中抛出异常而无法解除锁定,一定要在finally中调用Lock对象的unlock()方法。 Lock接口还定义了tryLock()方法,如果线程调用tryLock()可以取得锁定会返回true,若无法取得锁定并不会发生阻断,而是返回false。

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

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

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

使用Lock:lock接口主要操作类之一为ReentrantLock,可以达到synchronized的作用,也提供额外的功能。

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

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

使用Condition:Condition接口用来搭配Lock,最基本用法就是达到Object的wait()、notify()、notifyAll()方法的作用。

使用CharUtil.dump读入文档、转为字符串并显示在文本模式下:

import java.io.*;

public class CharUtilDemo {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader(args[0]);
StringWriter writer = new StringWriter();
CharUtil.dump(reader, writer);
System.out.println(writer.toString());
}
}

在命令行自变量指定了文档位置,若文档中实际都是字符数据,就可以在文档模式中看到文档中的文字内容。

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

关于ThreadGroup

java.lang.ThreadGroup类正如其名,可以管理群组中的线程。

interrupt()方法可以中断群组中所有线程。

setMaxPriority()方法可以设定群组中所有线程最大优先权。

activeCount()方法取得群组的线程数量,eunmerate()方法要传入Thread数组,这会将线程对象设定至每个数组索引。

public class ThreadGroupDemo {
public static void main(String[] args) {
ThreadGroup group = new ThreadGroup("group") {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
System.out.printf("%s: %s%n",
thread.getName(), throwable.getMessage());
}
};

Thread thread = new Thread(group, () -> {
throw new RuntimeException("测试异常");
});

thread.start();
}
}




uncaughException()方法第一个参数可取得发生异常的线程实例,第二个参数可取得异常对象,范例中

显示了线程的名称及异常信息

public class ThreadGroupDemo2 {

public static void main(String[] args) {
ThreadGroup group = new ThreadGroup("group");

Thread thread1 = new Thread(group, () -> {
throw new RuntimeException("thread1 测试例外");
});
thread1.setUncaughtExceptionHandler((thread, throwable) -> {
System.out.printf("%s: %s%n",
thread.getName(), throwable.getMessage());
});

Thread thread2 = new Thread(group, () -> {
throw new RuntimeException("thread2 测试异常");
});

thread1.start();
thread2.start();
}
}




每个线程都属于某个线程群组,如果没有指定,则归入产生该子线程的线程群组,也可以自行指定线程群组,线程一旦归入某个群组,就无法再更换。ThreadGroup的某些方法,可以对群组中所有线程产生作用。如果想要一次取得群组中所有线程,可以使用enumerate()方法。activeCount()方法取得群组的线程数量。

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

InputStream、Reader与Writer区别,还是有些模糊

Reader:用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。

Writer:写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。

Reader和Writer都属于字符流。

InputStream属于字节流。

InputStream:是表示字节输入流的所有类的超类。

本周代码托管截图



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

这周的概念也有不少,看起来还是比较费力,学习了输入输出,线程与并行API,所以不能一股脑全看完,这样不仅没印象而且还浪费不少时间,主要还是结合书上的代码,积极主动敲代码,主动发现问题。关于书上介绍的一些API,还有一些格式,他们的架构是怎样的,这些都需要不断巩固总结。

学习进度条

代码行数(新增/累积)博客量(新增/累积)学习时间(新增/累积)重要成长
目标4000行16篇400小时
第一周200/2002/220/20
第二周300/5001/325/45
第三周500/10001/440/85
第四周800/18001/545/130
第五周700/25001/643/173
第六周700/32001/748/221

参考资料

Java学习笔记(第8版)

《Java学习笔记(第8版)》学习指导
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: