教材学习内容总结

一.输入/输出

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. 【转】Problems with HTTPS, HttpWebRequest, and iOS?

    We're using HttpWebRequest to hit HTTPS urls, on iOS. In Debug, local builds, etc. everything works ...

  2. UML 关系

    1. 关联关系(association) 关联关系式是用一条直线表示的,如A—B.表示在一段时间内将多个类的实例连接在一起,关联关系描述了某个对象在一段时间内一直知道另一个对象的存在.在Rose中为了 ...

  3. Difference Search Path

    1.Framework Search Path           where to search frameworks (.framework bundles) in addition to sys ...

  4. gtd好文两篇收藏

    http://www.jianshu.com/p/bf5e8a9761f5 http://blog.sina.com.cn/s/blog_4e0f66b80100m73i.html

  5. python 之 推导式

    推导式 : 英文 comprehension 支持推导式的有列表list      字典dict      集合set      注意元组没有 推导式,如果你那样去写,他会变成一个generator生 ...

  6. 使用多种客户端消费WCF RestFul服务(四)——Jquery篇

    Jquery篇 互联网开发中少不了各类前端开发框架,其中JQUERY就是最流行之一,本篇我们就采用JQUERY来消费WCF RestFul服务,其中用到JSON基础知识,如果有想了解的朋友,请访问:& ...

  7. 默认的app.js

    我们通过npm start 默认入口是app.js,如果想默认入口改为main.js,可以修改项目下的/bin/www文件把app修改main var app = require('../app');

  8. java简单优化和编写规范,自己总结的。

    1.永远不要比较两个浮点数是否相等.它是不安全的.详情google. 2.尽量使用StringBuffer代替String. 3.final类会提高很多效率. 4.try-catch 不应该用来控制程 ...

  9. HTML文件基本结构

    固定结构: <html> <head>...</head> <body>...</body> </html>1,<html ...

  10. RepositoryItemComboBox 用法1

    RepositoryItemComboBox cbbEnd = new RepositoryItemComboBox(); cbbEnd.TextEditStyle = DevExpress.Xtra ...