我的课本是分为六个章节进行了介绍:
这篇主要总结前三章。
- 第一章 I/O流
- 第二章 线程
- 第三章 同步代码块
- 第四章 网络编程
- 第五章 XML解析
- 第六章 设计模式
第一章 I/O流
1.1
I/O流的分类:
按照数据流向可以分为:
输入流和输出流
按照操作方式分为:
字节流 InputStream和OutputStream
字符流 Reader和Writer
1.2
I/0流能做什么?
在本地磁盘和网络上操作数据
1.3
字节流与字符流的区别:
“字节流和字符流的区别在于每次读写的字节数不同;字符流是快读写,字节流是字节读写;字符流带有缓存,字节流没有。
1、字节流 :字节读写, 字节流(ASCII)处理二进制文件。
可以传输音频,视频,图片,文本等,传输数据的基本单位为字节。2、字符流:快读写 ,字符流(Unicode)处理文本文件。
只能传输纯文本,传输数据的基本单位为字符 字节流是由字节组成的; 字符流是由字符组成的。
Java里字符由两个字节组成. 1字符=2字节
1.4
File类常用的方法:
/*注意:只要涉及到盘符的都是双斜杠*/
package First; import java.io.File; import java.io.IOException; import java.util.Iterator; public class Text01 { /*题目:在电脑硬盘中,查看E://text4/name目录是否存在,如果不存在,则创建该目录 * 如果存在,则查找readme文件是否存在。如果readme.txt不存在,则创建readme.txt文件存在 * 输出该文件的路径和大小*/ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub // 判断是否存在 boolean flag=false; // 创建file对象 File directory=new File("E://text4/name"); // 判断目录是否存在 if (directory.exists()) { // 如果该目录存在,则获取该目录下所有的子文件和子目录 File[]fileArrayFiles=directory.listFiles(); // 遍历fileArray[]数组 // 高级for循环格式:for(数据类型 变量名 被遍历的集合或数组) for (File file:fileArrayFiles) { // 判断readme.txt是否存在 if ("readme.txt".equals(file.getName())) { // 如果存在 System.out.println("存在"); System.out.println("路径"+file.getAbsolutePath()); System.out.println("大小"+file.length()); // 设置flag为true flag=true; break; } } }else { // 如果不存在,则创建该目录 directory.mkdirs(); } // 如果该文件在目录中不存在,则创建 if (!flag) { try { File txtFile=new File(directory,"readme.txt"); txtFile.createNewFile(); System.out.println("文件已成功创建"+txtFile.getAbsolutePath()); } catch (IOException e) { // TODO: handle exception e.printStackTrace(); } } } }
以下是老师上课讲的一个案例,我记下来了,但是我没有听懂,懂的宝宝可以评论区告诉我一下。我只会背代码,/(ㄒoㄒ)/~~
假设我有一部电影需要拷贝,如果说它比较大,比如我们有40G,那么如果是采取读取完毕之后统一写入会怎样?
因为日常生活的我们的内存只有32G,读取内容超过了内存,那么就会出现数据不完善.
所以我们应该采取读一部分,写一部分,这样才算合理的运用资源,边读边写。
拷贝原理:从需要拷贝的文件,到需要拷贝的副本。
1.通过字节输入流,将文件输入到电脑当中,保存到内存当中。
2.字节输出流,使用字节输出流,将文件输出成对应的文件。
3.先开先读,后开后读。
下面开始背代码了:
## 1.1字符流,用来处理字符集的转换
package First;
import java.awt.Frame;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
public class Zifuliu1 {
public static void main(String[] args) {
FileReader fr =null;
FileWriter fw=null;
// TODO Auto-generated method stub
`try {`
`fr=new FileReader("E://笔记和作业//高级java//字符流更改文件/wen.txt");`
`fw=new FileWriter("E://笔记和作业//高级java//字符流更改文件/古诗.txt");`
`int data;//用来接收我们的数据`
`//用字节数组装好`
`byte[]buf=new byte[1024];`
`while ((data=fr.read())!=1) {`
`// 将数据写入文件中`
`fw.write(data);`
`}`
`} catch (Exception e) {`
`e.printStackTrace();`
`}finally {`
`try {`
`if (fr!=null) {`
`fr.close();`
`}`
`if (fw!=null) {`
`fw.close();`
`}`
`} catch (Exception e2) {`
`e2.printStackTrace();`
`}`
`}`
`}`
`}`
## 1.2字节流可以传输音频,视频,图片,文本等,传输数据的基本单位为字节。
`package First;`
`import java.io.FileInputStream;`
`import java.io.FileOutputStream;`
`import java.nio.Buffer;`
`public class zijieliu1 {`
`//使用字节流来拷贝文件`
`public static void main(String[] args) {`
`// TODO Auto-generated method stub`
`FileInputStream fis=null;`
`FileOutputStream fos=null;`
`try {`
`// 需要拷贝的文件`
`fis=new FileInputStream("E://笔记和作业//高级java//音乐素材/遗失的心跳.mp3");`
`// 拷贝后的副本`
`fos=new FileOutputStream("E://笔记和作业//高级java//拷贝后的素材/遗失的心跳.mp3");`
``
int data;//用来接收我们的数据
//用字节数组装好
byte[]buf=new byte[1024];
long start=System.currentTimeMillis();//拷贝时间
while ((data=fis.read(buf))!=-1) {
fos.write(buf,0,data);
}
long end=System.currentTimeMillis();
System.out.println("拷贝时间为:"+(end-start));
System.out.println("拷贝成功");
``
`} catch (Exception e) {`
`// TODO: handle exception`
`e.printStackTrace();`
`}finally {`
`try {`
`if (fis!=null) {`
`fis.close();`
`}`
`if (fos!=null) {`
`fos.close();`
`}`
`} catch (Exception e2) {`
`e2.printStackTrace();`
`}`
`}`
`}`
`}`
第二章 线程
2.1一个进程多个线程
什么是多线程?通俗来讲,为了提高CPU的利用率,从而更好完成任务,我们可以使用多个线程实现同一个功能内容,相当于找个多个人同时搬砖。
创建多线程的三种方式 1.继承Thread类(线程类)2.实现runnable接口实现线程 3.Callable接口创建线程
主要掌握前两种,推荐使用Runnable接口实现线程。
2.2第一种 继承Thread类
`步骤:
1.定义Thread类的子类
2.重写run()方法
3.创建子类实例,调用start启动线程
``package First;`
`import java.util.Iterator;`
`public class Xiancheng extends Thread{`
`//实现多线程的方式第一种,继承Thread类`
`public static void main(String[] args) {`
`// TODO Auto-generated method stub`
`Xiancheng xiancheng=new Xiancheng("小猫");`
`Xiancheng xiancheng2=new Xiancheng("小狗");`
`Xiancheng xiancheng3=new Xiancheng("小鸡");`
`//我们有三个线程,一个进程`
`// 为什么有的同学跑得快,因为是抢占式的 随机`
`xiancheng.start();`
`xiancheng2.start();`
`xiancheng3.start();`
}
private String name;
`// 有参构造方法`
`public Xiancheng(String name) {`
`this.name=name;`
`}`
`public void run() {`
`for (int i = 0; i < 50; i++) {`
`System.out.println(this.name+"同学跑了第"+i+"米");`
`}`
`}`
2.3线程休眠应用,控制线程(sleep)
`public class Xianchenxiumian1 extends Thread{`
public static void main(String[] args) {
// TODO Auto-generated method stub
Xianchenxiumian1 xianchenxiumian1=new Xianchenxiumian1();
xianchenxiumian1.start();
}
```
`public void run() {`
`for (int i = 0; i < 20; i++) {`
`System.out.println("今天天气真的好"+i);`
`try {`
`Thread.sleep(1000);`
`} catch (Exception e) {`
`e.printStackTrace();`
`}`
`}`
`}`
``
`}`
2.4第二种 实现Runnable接口实现线程
public class SellTicket implements Runnable{
/*题目是三个窗口一起卖火车票
卖50张火车票 */
public static void main(String[] args) {
//创建实例
SellTicket sellTicket=new SellTicket();
Thread thread1=new Thread(sellTicket);
thread1.setName("窗口一");
Thread thread2=new Thread(sellTicket);
thread2.setName("窗口二");
Thread thread3=new Thread(sellTicket);
thread3.setName("窗口三");`
// 实际启动
thread1.start();
thread2.start();
thread3.start();
}
private int ticket=50;
//多线程抢到了同一张票
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
//实现接口的时候 我们查询线程名称需要用到thread.currentThread.getname
System.out.println(Thread.currentThread().getName()+"出售第"+ticket+"张火车票");
ticket--;
if (ticket<=0) {
break;
}
}
}
}
2.5线程和进程的关系:
进程是操作系统分配资源的基本单位,线程是操作系统执行和调度的最小单位,线程依赖于进程而存在,即线程和进程是依赖关系,通俗的讲,就是进程是一个容器,操作系统通过运行进程容器中的线程,来完成应用程序进程中的各项功能。
第三章 同步代码块和同步方法体
3.1多线程安全问题
线程抢占式执行会出现狼多肉少的情况,会导致线程不安全,多线程中会有抢占式调度。
书本案例:
关于线程安全,有一个经典的问题——银行取钱。
取钱可以分为四个步骤:
1.用户输入取款金额
2.系统判断账户余额是否大于取款金额
3.如果余额大于等于取款金额,则取款成功,否则取款失败
//首先创建了Account类,再封装了账号String no和余额double balance
//这是实现多线程模拟取钱 即多个线程对一个账户进行取钱
//必须是一个多线程的类
public class DreamThread extends Thread{
//取钱的账号对象
private Account account;
//当前线程所取的钱数
private double dreamAccount;
// 需要加入一个有参构造器,创建多线程的时候,就可以人为的设置人为的金额。
// 第一个参数代表线程是谁 取钱
public DreamThread(String name,Account account,double dreamAccount) {
super(name);
this.account=account;
this.dreamAccount=dreamAccount;
}
public void run(){
account.draw(dreamAccount);
}
public static void main(String[] args) {
// TODO Auto-generated method stubAccount account=new Account("1221",1200);
new DreamThread("张三", account, 650).start();
new DreamThread("李四", account, 650).start();
}
}
## 最后的运行结果是,两个线程对一个账户取钱。出现了-550元
因此为了避免这种问题的出现,
同步代码块的语法格式:
Sychronized(要锁定的对象){
//同步代码块执行体
}
同步方法的语法格式:
访问修饰符 sychronized 返回值类型 方法名称 (方法参数){
//同步方法的方法体
}
代码修改后:
public class SyncThread extends Thread{
//模拟用户账户
// 新建的类 对象
private Account account;
// 当前线程所取的钱数
private double drawAccount;
public SyncThread(String name,Account account, double drawAccount) {
super(name);
this.account = account;
this.drawAccount = drawAccount;
}
//执行
public void run(){
synchronized (account){
if (account.getBalance()>=drawAccount){
System.out.println(this.getName()+"\t取款成功!取出"+drawAccount);
// 修改余额
account.setBalance(account.getBalance()-drawAccount);
System.out.println("\t余额"+account.getBalance());
}else{
System.out.println(this.getName()+"取钱失败!余额不足");
}
}
}
public static void main(String[] args) {
// 创建一个账户
Account account=new Account("221322421",1200);
// 模拟两个线程对一个账户取钱
new SyncThread("张三",account,650).start();
new SyncThread("李四",account,650).start();
}
}
运行结果:
张三 取款成功!取出650.0
余额550.0
李四取钱失败!余额不足
3.2 模拟三个窗口出售50张车票的例子:
实现思路:
1.创建一个类并且继承Runnable接口
2.定义int类型的变量ticket,表示剩余的车票数量,并实现Runnable接口
3.创建同步方法sellTicket()。在该方法体,判断ticket的值是否大于0,如果大于0,则调用Thread.sleep(long mills)方法,让线程休眠50毫秒,并且打印出当前窗口的售票情况
4.重写run()方法,在 run()方法内,定义一个while死循环,在循环内,判断变量ticket是否大于0,小于0,结束循环,大于0,调用sellTicket方法
5.在main方法创建接口实例。
6.创建三条线程,并且为三条线程指定名称
7.依次启动线程
public class SellTicketBySync implements Runnable{
private int ticket=50;
@Override
public void run() {
while (true){
if (this.ticket>0){
sellTicket();
}else {
break;
}
}
}
public synchronized void sellTicket(){
if (this.ticket>0){
try{
// 线程休眠50毫秒
Thread.sleep(50);
System.out.println(Thread.currentThread().getName()+"出售第"+ticket--+"张车票");
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// 创建Runnable 实例
SellTicketBySync runnableInstance = new SellTicketBySync();
// 创建三条线程,并为线程指定名称
Thread thread01=new Thread(runnableInstance,"窗口一");
Thread thread02=new Thread(runnableInstance,"窗口一");
Thread thread03=new Thread(runnableInstance,"窗口一");
thread01.start();
thread02.start();
thread03.start();
}
}