教材学习内容总结

一.输入/输出

InputStreamOutputstream

串流设计的概念

从应用程序角度看,将数据从来源取出,可以使用输入串流,将数据写入目的地,可以使用输出串流;在Java中,输入串流代表对象为java.io.InputStream实例,输出串流代表对象为java.io.OutputStream实例;

串流继承框架

System.in与System.out分别代表标准输入和标准输出;

可以使用System的setIn()方法指定InputStream实例,用setOut()方法指定printStream;代码如下:

System.err为printStream实例,称为标准输出串流,用于立即显示错误信息;

FileInputStream:是InputStream的子类,可以指定文件名创建实例,一旦创建文档就开启,接着就可以用来写出数据,主要操作了InputStream的read()抽象方法,从而读取文档中的数据;

FileOutputStream:是OutputStream的子类,可以指定文件名创建实例,一旦创建文档就开启,接着就可以用来写出数据,主要操作了OutputStream中的write抽象方法,使之可写出数据到文档;

不使用,时都要用close()关闭文档;

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

串流装饰处理器

若想要为输入输出的数据作加工处理,可以使用打包器类(如:scanner);

InputStream和OutputStream的一些子类也具有打包器的作用,这些子类创建时,可以接受InputStream和OutputStream实例;

常用打包器:BufferedInputStream、BufferOutputSream(具备缓冲区作用),DataInputStream、DataOutputStream(具备数据转换处理作用),ObjectInputStream、ObjectOutputStream(具备对象串行化能力)等;代码如下:

package cc.openhome;

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);

}

}

}

}

package cc.openhome;

import java.io.*;

public class Member {

private String number;

private String name;

private int age;

public Member(String number, String name, int age) {

this.number = number;

this.name = name;

this.age = age;

}

public String getNumber() {

return number;

}

public void setNumber(String number) {

this.number = number;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

@Override

public String toString() {

return String.format("(%s, %s, %d)", number, name, age);

}

public void save() throws IOException {

try(DataOutputStream output =

new DataOutputStream(new FileOutputStream(number))) {

output.writeUTF(number);

output.writeUTF(name);

output.writeInt(age);

}

}

public static Member load(String number) throws IOException {

Member member;

try(DataInputStream input =

new DataInputStream(new FileInputStream(number))) {

member = new Member(

input.readUTF(), input.readUTF(), input.readInt());

}

return member;

}

}

package cc.openhome;

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"));

}

}

import static java.lang.System.out;

public class Member2Demo {

public static void main(String[] args) throws Exception {

Member2[] members = {new Member2("B1234", "Justin", 90),

new Member2("B5678", "Monica", 95),

new Member2("B9876", "Irene", 88)};

for(Member2 member : members) {

member.save();

}

out.println(Member2.load("B1234"));

out.println(Member2.load("B5678"));

out.println(Member2.load("B9876"));

}

}

字符处理类

• Reader与Writer继承架构

java.io.Reader类:抽象化了字符数据读入的来源;

java.io.Writer类:抽象化了数据写出目的地;代码如下:

FileReader:读取文档并将读到的数据转换成字符;StringWriter:将字符数据写至它最后使用toString()的方法取得字符串;代码如下:

import java.io.*;

public class CharUtil {

public static void dump(Reader src, Writer dest) throws IOException {

try(Reader input = src; Writer output = dest) {

char[] data = new char[1024];

int length;

while((length = input.read(data)) != -1) {

output.write(data, 0, length);

}

}

}

}

package cc.openhome;

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对串流数据打包;代码如下:

import java.io.*;

public class CharUtil2 {

public static void dump(Reader src, Writer dest) throws IOException {

try(Reader input = src; Writer output = dest) {

char[] data = new char[1024];

int length;

while((length = input.read(data)) != -1) {

output.write(data, 0, length);

}

}

}

public static void dump(InputStream src, OutputStream dest,

String charset) throws IOException {

dump(

new InputStreamReader(src, charset),

new OutputStreamWriter(dest, charset)

);

}

// 采用预设编码

public static void dump(InputStream src, OutputStream dest)

throws IOException {

dump(src, dest, System.getProperty("file.encoding"));

}

}

提高字符输入输出效率,提供缓冲区作用:BufferedReader、BufferWriter;

printWriter:对OutStream打包,对writer打包;

.线程与并行API

线程

线程简介

单线程程序:启动的程序从main()程序进入点开始至结束只有一个流程;多线程程序:拥有多个流程;

java中从main()开始的流程会由主线程执行可以创建Thread实例来执行Runable实例定义的run()方法;代码如下:(龟兔赛跑)

package cc.openhome;

public class Tortoise implements Runnable {

private int totalStep;

private int step;

public Tortoise(int totalStep) {

this.totalStep = totalStep;

}

@Override

public void run() {

while (step < totalStep) {

step++;

System.out.printf("乌龟跑了 %d 步...%n", step);

}

}

}

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);

}

}

}

}

public class TortoiseHareRace2 {

public static void main(String[] args) {

Tortoise tortoise = new Tortoise(10);

Hare hare = new Hare(10);

Thread tortoiseThread = new Thread(tortoise);

Thread hareThread = new Thread(hare);

tortoiseThread.start();

hareThread.start();

}

}

• ThreadRunnable

创建Thread实例就是为JVM加装CPU,启动额外CPU就是调用实例的start()方法,额外CPU的进入点可以定义在Runable接口的run()方法中;

除了将流程这样定义,另一个撰写多线程程序的方式就就是继承Thread类,重新定义run()方法;

操作Runnable接口的好处就是较有弹性,你的类还有机会继承其他类;若继承了Thread类,通常是为了直接利用Thread中定义的一些方法;

线程生命周期

Daemon线程:如果一个Thread被标示为Deamon线程,在所有的非Deamon线程都结束时,JVM就会自动终止;代码如下:

public class DaemonDemo {

public static void main(String[] args) {

Thread thread = new Thread(() -> {

while (true) {

System.out.println("Orz");

}

});

// thread.setDaemon(true);

thread.start();

}

}

Thread基本状态图:可执行、被阻断、执行中;

线程看起来但事实是同一个时间点上,一个CPU还是只能执行一个线程,只是因其不断切换且很快,所以看起来像是同时执行;

线程有其优先权,setPriority()方法设定优先权,利用多线程改进效能;

当线程使用join()加入另一线程时,另一线程会等待被加入的线程工作完毕再继续它的动作;代码如下:

线程完成run()方法后,就会进入Dead,此时不可以再调用start()方法否则会抛出IlligleThreadException;

关于ThreadGroup

每个线程都属于某个线程群组,线程一旦归入某个群组,就无法再更换;可以使用以下程序片段取得当前线程所属线程群组名:Thread.currentThread().getThreadGroup().getname();

使用uncoughtException()方法处理群组中某个线程出现异常未被捕捉的情况,可以重新定义此方法;
代码如下:

package cc.openhome;

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();

}

}

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();

}

}

• synchronizedvolatile

如果在方法上标示synchronized,则执行方法必须取得该实例的锁定,才能执行该区块内容;

可重入同步:线程取得某对象锁定后,若执行过程中又要执行synchronized,尝试取得锁定的对象来源又是同一个,则可以直接执行;

synchronized:互斥性:该区块同时间只能有一个线程,可见性:线程离开该区块后,另一线程接触到的就是上一线程改变后的对象状态;

在java中对于可见性的要求,可以使用volatile达到变量范围,在变量上声明volatile,表示变量是不稳定、易变的,也就是可能在多线程下存取,其存取一定是在共享内存中进行,代码如下:

package cc.openhome;

class Variable1 {

static int i = 0, j = 0;

static void one() {

i++;

j++;

}

static void two() {

System.out.printf("i = %d, j = %d%n", i, j);

}

}

public class Variable1Test {

public static void main(String[] args) {

Thread thread1 = new Thread(() -> {

while (true) {

Variable1.one();

}

});

Thread thread2 = new Thread(() -> {

while (true) {

Variable1.two();

}

});

thread1.start();

thread2.start();

}

}

class Variable2 {

static int i = 0, j = 0;

static synchronized void one() {

i++;

j++;

}

static synchronized void two() {

System.out.printf("i = %d, j = %d%n", i, j);

}

}

public class Variable2Test {

public static void main(String[] args) {

Thread thread1 = new Thread(() -> {

while (true) {

Variable2.one();

}

});

Thread thread2 = new Thread(() -> {

while (true) {

Variable2.two();

}

});

thread1.start();

thread2.start();

}

}

class Variable3 {

volatile static int i = 0, j = 0;

static void one() {

i++;

j++;

}

static void two() {

System.out.printf("i = %d, j = %d%n", i, j);

}

}

public class Variable3Test {

public static void main(String[] args) {

Thread thread1 = new Thread(() -> {

while (true) {

Variable3.one();

}

});

Thread thread2 = new Thread(() -> {

while (true) {

Variable3.two();

}

});

thread1.start();

thread2.start();

}

}

等待与通知

调用锁定对象的wait()方法,线程会释放对象锁定,并进入对象等待集合而处于阻断状态,其他线程可以竞争对象锁定,取得锁定的线程可以执行synchronized范围的代码;

被竞争的对象调用notify()方法时,会从对象等待集合中随机通知一个线程加入排班,再次执行synchronized前,被通知的线程会与其他线程共同竞争对象锁定;代码如下:

public class Consumer implements Runnable {

private Clerk clerk;

public Consumer(Clerk clerk) {

this.clerk = clerk;

}

public void run() {

System.out.println("消费者开始消耗整数......");

for(int i = 1; i <= 10; i++) {

try {

clerk.getProduct();

} catch (InterruptedException ex) {

throw new RuntimeException(ex);

}

}

}

}

public class Clerk {

private int product = -1;

public synchronized void setProduct(int product) throws InterruptedException {

waitIfFull();

this.product = product;

System.out.printf("生产者设定 (%d)%n", this.product);

notify();

}

private synchronized void waitIfFull() throws InterruptedException {

while (this.product != -1) {

wait();

}

}

public synchronized int getProduct() throws InterruptedException {

waitIfEmpty();

int p = this.product;

this.product = -1;

System.out.printf("消费者取走 (%d)%n", p);

notify();

return p;

}

private synchronized void waitIfEmpty() throws InterruptedException {

while (this.product == -1) {

wait();

}

}

}

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();

}

}

并行API

• lockReadWriteLockCondition

java.util.concurrent.locks包中提供Lock、ReadWriteLock、Condition接口以及相关操作类,可以提供类似synchronized、wait()、notify()、notifyall()的作用,以及更多高级功能;

Lock接口主要操作类之一为ReentrantLook,可以达到synchronized的作用,也提供额外功能;代码如下:

ReadWriteLock:如果已经有线程取得Lock对象锁定,尝试再次锁定同一Lock对象是可以的。想要锁定Lock对象,可以调用Lock()方法;

Condition接口用来搭配Lock,一个Condition对象可代表一个等待集合,可以重复调用Lock的newCondition(),取得多个Condition实例,这代表了有多个等待集合;

使用Executor

java.util.concurrent.Executor接口,目的是将Runnable的指定与实际如何执行分离,Executor接口只定义了一个execute();

像线程池这样类服务的行为,实际上是定义在Executor的子接口java.util.concurrent.ExecutorService当中,通用的ExecutorService由抽象类AbstractExecutorService操作,如果需要线程池的功能,则可以使用其子类java.util.concurrent.ThreadPoolExecutor;

ExecutorService还定义了submit()、invokeAll()、invokeAny()等方法,这些方法中出现了java.util.concurrent.Future、java.util.concurrent.Callable接口;

ScheduledExecutorService为ExecutorService的子接口,可以进行工作排程,schedule()方法用来排定Runnable或Callable实例延迟多久执行一次,并返回Future子接口ScheduledFuture的实例;

并行Collection简介

java.util.concurrent包中,提供一些支持并行操作的Collection子接口与操作类;

CopyOnWriteArrayList操作了List接口,这个类的实例在写入操作时,内部会建立新数组,并复制原有数组索引的参考,然后在新数组上进行写入操作,写入完成后,再将内部原参考旧数组的变量参考至新数组;

CopyOnWriteArraySet操作了Set接口,内部使用CopyOnWriteArrayList来完成Set的各种操作,因此一些特性与CopyOnWriteArrayList是相同的;

BlockingQueue是Queue的子接口,新定义了put()、take()方法;代码如下:

import java.util.concurrent.BlockingQueue;

public class Producer3 implements Runnable {

private BlockingQueue<Integer> productQueue;

public Producer3(BlockingQueue<Integer> productQueue) {

this.productQueue = productQueue;

}

public void run() {

System.out.println("生产者开始生产整数......");

for(int product = 1; product <= 10; product++) {

try {

productQueue.put(product);

System.out.printf("生产者提供整数 (%d)%n", product);

} catch (InterruptedException ex) {

throw new RuntimeException(ex);

}

}

}

}

import java.util.concurrent.BlockingQueue;

public class Consumer3 implements Runnable {

private BlockingQueue<Integer> productQueue;

public Consumer3(BlockingQueue<Integer> productQueue) {

this.productQueue = productQueue;

}

public void run() {

System.out.println("消费者开始消耗整数......");

for(int i = 1; i <= 10; i++) {

try {

int product = productQueue.take();

System.out.printf("消费者消耗整数 (%d)%n", product);

} catch (InterruptedException ex) {

throw new RuntimeException(ex);

}

}

}

}

import java.util.concurrent.*;

public class ProducerConsumerDemo3 {

public static void main(String[] args) {

BlockingQueue queue = new ArrayBlockingQueue(1);

new Thread(new Producer3(queue)).start();

new Thread(new Consumer3(queue)).start();

}

}

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

这两章的内容是最多的,是真的多!但是在理解方面,并没有前面的概念性的知识难理解,在将书上的代码敲过一些之后,对于这些内容就有了很好地理解。但是书上东西实在太多了!!!好了不说了,焊电表去了

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

p345,有关volatile部分不太清楚。
package cc.openhome;

class Variable1 {
    static int i = 0, j = 0;
 
    static void one() {
        i++;
        j++;
    }
 
    static void two() {
        System.out.printf("i = %d, j = %d%n", i, j);
    }
}
 
public class Variable1Test {
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            while (true) {
                Variable1.one();
           }
            });
    Thread thread2 = new Thread(() -> {
            while (true) {
                Variable1.two();
            }
        });
    
        thread1.start();
        thread2.start();
    }
}

j远大于i不理解,晚上我问问同学。

20145207《Java程序设计》第6周学习总结的更多相关文章

  1. 20145213《Java程序设计》第九周学习总结

    20145213<Java程序设计>第九周学习总结 教材学习总结 "五一"假期过得太快,就像龙卷风.没有一点点防备,就与Java博客撞个满怀.在这个普天同庆的节日里,根 ...

  2. 20145213《Java程序设计》第二周学习总结

    20145213<Java程序设计>第二周学习总结 教材学习内容总结 本周娄老师给的任务是学习教材的第三章--基础语法.其实我觉得还蛮轻松的,因为在翻开厚重的书本,一股熟悉的气息扑面而来, ...

  3. 20145213《Java程序设计》第一周学习总结

    20145213<Java程序设计>第一周学习总结 教材学习内容总结 期待了一个寒假,终于见识到了神秘的娄老师和他的Java课.虽说算不上金风玉露一相逢,没有胜却人间无数也是情理之中,但娄 ...

  4. 21045308刘昊阳 《Java程序设计》第九周学习总结

    21045308刘昊阳 <Java程序设计>第九周学习总结 教材学习内容总结 第16章 整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 数据库本身是个独立运行的应用程序 撰 ...

  5. 20145330孙文馨 《Java程序设计》第一周学习总结

    20145330孙文馨 <Java程序设计>第一周学习总结 教材学习内容总结 刚开始拿到这么厚一本书说没有压力是不可能的,开始从头看觉得很陌生进入不了状态,就稍微会有一点焦虑的感觉.于是就 ...

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

    20145337 <Java程序设计>第九周学习总结 教材学习内容总结 数据库本身是个独立运行的应用程序 撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找 JDBC可以 ...

  7. 20145337 《Java程序设计》第二周学习总结

    20145337 <Java程序设计>第二周学习总结 教材学习内容总结 Java可分基本类型与类类型: 基本类型分整数(short.int.long).字节(byte).浮点数(float ...

  8. 20145218《Java程序设计》第一周学习总结

    20145218 <Java程序设计>第一周学习总结 教材学习内容总结 今天下午看了Java学习的视频,感觉很是新奇,之前觉得Java学起来是艰难枯燥的,但通过第一章的学习觉得如果自己可以 ...

  9. 《Java程序设计》第九周学习总结

    20145224 <Java程序设计>第九周学习总结 第十六章 整合数据库 JDBC入门 ·数据库本身是个独立运行的应用程序 ·撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的 ...

  10. 《Java程序设计》第二周学习总结

    20145224陈颢文<Java程序设计>第二周学习总结 教材学习内容总结 一.类型.变量与运算符 1.类型 整数: 可细分为为short整数(占2字节),int整数(占4字节),long ...

随机推荐

  1. http安全篇

    一.app与服务端交互确保来源的安全 作为一个移动互联网App,天生是需要和服务器通信的.那么,服务器如何识别客户端的身份?我们如何保证数据传输过程中的安全性?要靠两个东西:使用AppKey做身份识别 ...

  2. [转]C++ string的trim, split方法

    很多其他语言的libary都会有去除string类的首尾空格的库函数,但是标准C++的库却不提供这个功能.但是C++string也提供很强大的功能,实现trim这种功能也不难.下面是几种方法: 1.使 ...

  3. yum change source repo centos共存安装sun jdk6和jdk7

    之前一直使用的是163的源,今天从微博看到阿里云推出了自己的源.因为我的主机是阿里云,所以可以走内网,速度提升更快.过程如下:cd /etc/yum.repos.d/mv mv CentOS-Base ...

  4. 【Android测试】【随笔】模拟长按电源键

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5195121.html 起因 昨天群里看到有人问如何实现一个 ...

  5. 【Android开发学习笔记】【高级】【随笔】插件化——Activity生命周期

    前言 如同第一章我们说的,宿主程序通过 dexclassloader 将插件的类加载进来,然后通过反射去调用它的方法,这样Activity就被当成了一个普通的类来执行了,因此系统不再接管它的生命周期, ...

  6. GitLab使用方法

    注意只有master权限的用户才可以push到主线master分支上(默认受保护)(当一个新版本的app定版之后,才会提交到master分支上,平时不建议使用该分支),developer没有push到 ...

  7. Top Five Communication Skills for Project Managers

    Research among project managers globally identifies top communication skills for leading teams. Lead ...

  8. iOS _BSMachError: (os/kern) invalid capability (20)

    _BSMachError: (os/kern) invalid capability (20) 解决办法:将info.plist里面的en改为United States 2016-04-18 22:4 ...

  9. Selenium2学习-001-Selenium2 WebUI自动化Java开发 Windows 环境配置

    此文主要介绍 Selenium2 WebUI自动化Java开发 Windows 环境配置,供各位亲们参考,若有不足之处,敬请各位大神指正,非常感谢! 所需软件列表如下所示: 所属分类 具体名称 备注 ...

  10. 链表之求链表倒数第k个节点

    题目描述:输入一个单向链表,输出该链表中倒数第k个节点,链表的倒数第0个节点为链表的尾指针. 最普遍的方法是,先统计单链表中结点的个数,然后再找到第(n-k)个结点.注意链表为空,k为0,k为1,k大 ...