java-day11

  1. 1. 转换流
    1. 1.1. 含义
    2. 1.2. 种类
    3. 1.3. 案例一
    4. 1.4. 案例二
  2. 2. 序列化 & 反序列化
    1. 2.1. 序列化
    2. 2.2. 反序列化含义
    3. 2.3. 要求
    4. 2.4. 案例
  3. 3. 打印流
    1. 3.1. 含义
    2. 3.2. 注意点
    3. 3.3. 种类
    4. 3.4. 案例
  4. 4. 线程
    1. 4.1. 相关概念
    2. 4.2. 进程和线程区别
    3. 4.3. 如何创建线程
    4. 4.4. 入门案例
      1. 4.4.1. 示意图
      2. 4.4.2. 代码
  5. 5. 常见的方法上
    1. 5.1. 案例
    2. 5.2. 示意图
  6. 6. 两种方式
    1. 6.1. 区别
    2. 6.2. 案例
      1. 6.2.1. 继承方式
      2. 6.2.2. 实现接口方式
  7. 7. 线程安全
    1. 7.1. 常见概念
    2. 7.2. 处理方案
    3. 7.3. 案例一
    4. 7.4. 案例二
    5. 7.5. 案例三
    6. 7.6. 案例四
  8. 8. 单例
    1. 8.1. 含义
    2. 8.2. 方式
  9. 9. 懒汉式
    1. 9.1. 步骤
    2. 9.2. 代码
  10. 10. 常见方法下
    1. 10.1. 判断是否存活
    2. 10.2. 线程优先级
    3. 10.3. 线程中断

转换流

含义

:字节流装成字符流

种类

  • InputSteamReader

    将字节输入流转为字符输入流

  • OutputStreamWriter

    将字节输出流转为字符输出流

案例一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class _01ByteInputToCharInput {

public static void main(String[] args) {

BufferedReader bufferedReader=null;
try {
//字节流
InputStream inputStream = new FileInputStream("C:\\11.txt");

//字符流【转换流:将字节流转换字符流】
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

bufferedReader = new BufferedReader(inputStreamReader);

System.out.println(bufferedReader.readLine());

} catch (IOException e) {
e.printStackTrace();
}finally {
if(bufferedReader!=null){
try {
bufferedReader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}
}

案例二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class _02ByteOutToCharOutput {

public static void main(String[] args) {


OutputStreamWriter outputStreamWriter=null;
try {
OutputStream outputStream = new FileOutputStream("C:\\22.txt",true);

//InputStreamReader:转换流:byteInput-->charInput
//OutputStreamWriter:转换流:byteOutput-->charOnput

outputStreamWriter = new OutputStreamWriter(outputStream);

outputStreamWriter.write("\r\n中国你好\r\n");
outputStreamWriter.write("台湾你好\r\n");

} catch (IOException e) {
e.printStackTrace();
}finally {
if(outputStreamWriter!=null){
try {
outputStreamWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}

序列化 & 反序列化

序列化

  • 将对象转成二进制并保存到磁盘中

    对象需要实现序列化接口

反序列化含义

  • 将磁盘中的二进制对象加载到内存中

    对象需要实现序列化接口

要求

  • 包名序列化前后也要一样

  • 实现Serializable接口

  • 生成一个版本号

    作用:用来校验类是否修改过

案例

User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class User implements Serializable{

/**
* 根据类的信息生成
*/
private static final long serialVersionUID = -3986195817302832270L;

private String name;
private Integer num;

public User(String name, Integer num) {
super();
this.name = name;
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
@Override
public String toString() {
return "User [name=" + name + ", num=" + num + "]";
}
}

Test.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class Test {

public static void main(String[] args) {
//序列化
//对象--->磁盘中
//对象--->网络上


//要求
//User类实现序列化接口
//版本

String target = "C:\\xx.txt";
/*
User one = new User("zhangsan",100);
System.out.println(one);

objectOutput(target,one);
*/

User result = objectInput(target);
System.out.println(result);
}


/**
* 序列化
* @param user
*/
private static void objectOutput(String target,User user) {


//输出到磁盘文件中,使用对象的输出流

OutputStream outputStream=null;
ObjectOutputStream objectOutputStream=null;
try {
outputStream = new FileOutputStream(target);
objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(user);

} catch (IOException e) {
e.printStackTrace();
}finally {
if(objectOutputStream!=null){
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


private static <T> T objectInput(String path){

ObjectInputStream objectInputStream=null;
try {
objectInputStream = new ObjectInputStream(new FileInputStream(path));

return (T) objectInputStream.readObject();


} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}finally {
if(objectInputStream!=null){
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}

打印流

含义

可以输出任何类型的数据

注意点

当打印对象的时候,只是输出了对象.toString()结果。并不是将整个对象输出。

种类

  • PrintStream
  • PrintWriter [掌握]

案例

User.java

1
2
3
4
5
6
7
8
9
10
11
public class User {

private String name;
public User(String name){
this.name = name;
}
@Override
public String toString() {
return "User [name=" + name + "]";
}
}

PrintTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class PrintTest {

//打印流
//含义:输出流
//作用:打印任何类型的数据,打印对象其实打印对象的toString方法的结果
 
public static void main(String[] args) throws IOException {

//Servlet
PrintWriter printWriter = new PrintWriter("C:\\result.txt");

User user = new User("zs");
printWriter.print(user);
printWriter.print(11);
printWriter.close();
}
}

线程

相关概念

  • 串行

    多个事件依次执行

  • 并行

    多个事件在同一时刻同时执行

  • 并发

    在一段时间内多个事件发生

  • 进程

    一个正在运行软件,一个软件对应一个进程

    一个进程中至少有个一个线程

  • 线程

    是进程中的执行分支(索引)

进程和线程区别

  • 每个进程都有独立的内存空间
  • 一个进程至少要有一个线程
  • 每创建一个线程都有自己的栈、本地方法区、程序计数器【TODO】

如何创建线程

  • 继承Thread
  • 实现Runnable接口

入门案例

示意图

1659497893768

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class _01Thread {

//进程
//含义:一个正在运行的软件
//特点
//操作分配的独立的内存空间 【进程通信】
//至少一个线程

//线程
//含义:执行的分支

//串行
//并行
//并发


//需求
//软件
//玩游戏 进程
//听音乐 进程
//软件【单核】
//玩游戏 线程
//听音乐 线程

//微观角度
//同一时刻只能有一个线程在运行
//宏观角度
//一起执行【交替执行】


//如何创建线程
//extends Thread
//implements Runnable


public static void main(String[] args) {

//启动线程
Thread firstThread = new FirstThread();
firstThread.start();

for(int i=0;i<20;i++){
System.out.println("Main,i="+i);
}

}
}

class FirstThread extends Thread{

//任务
@Override
public void run() {

for(int i=0;i<20;i++){
System.out.println("FirstThread,i="+i);
}
}
}

常见的方法上

  • Thread.currentThread()

    获取当前线程对象

  • start

    启动线程【此时是就绪状态并不是说马上执行该线程的任务,而是需要等待获得cpu运行时】

  • run

    指定线程的任务

  • getId

    获取线程的id

  • getName

    获取线程的名称

  • setName

    设置线程的名称,还可以在构造器中调用父类的super(String threadName)

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.neu.day11._04thread;

public class _02Thread {

//Thread.currentThread(); //获取当前的对象

//getName //获取线程的名称
//setName //设置线程的名称,还可以在构造器中调用父类的super(String threadName)
//getId //获取线程的id
//run //指定任务
//start //启动【不是立马执行,变成就绪状态】

public static void main(String[] args) {

/*
Thread curThread = Thread.currentThread();
System.out.println(curThread);
System.out.println(curThread.getName());
System.out.println(curThread.getId());

*/

Thread one = new MyThread("java");
one.start();

//System.out.println("one:name="+one.getName());
//System.out.println("one:id="+one.getId());

Thread two = new MyThread("html");
//two.setName("xxxxxxxxxxx");
two.start();

//System.out.println("two:name="+two.getName());
//System.out.println("two:id="+two.getId());


System.out.println("main....");

}

}

class MyThread extends Thread{

private String content;
public MyThread(String content){
super("thread:"+content);
this.content = content;
}


/**
* 指定任务
*/
@Override
public void run() {
//Thread curThread = Thread.currentThread();

//System.out.println(curThread==this);
//System.out.println(curThread.getName()+"="+this.content);
System.out.println(this.getName()+"="+this.content);
}
}

示意图

1659506782288

两种方式

区别

  • 实现方式可以共享资源,继承不可以共享资源
  • 实现方式还可以继承其他类,继承方式不可以再继承其他类了
  • 资源共享方式有线程安全问题

案例

继承方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class _01BuyTicket {	
public static void main(String[] args) {

Thread one = new BuyThreader();
Thread two = new BuyThreader();

one.start();
two.start();
}

}

class BuyThreader extends Thread{

private int ticket = 10;

//指定任务
@Override
public void run() {

while(ticket>0){
System.out.println("当前购买的票是:"+ticket);
ticket = ticket - 1;

try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

实现接口方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.neu.day11._05thread;

public class _02BuyTicket {


//创建线程的方式
//extends Thread
//implements Runnable

// 继承 vs 实现
//实现方式可以共享资源,继承不可以共享资源
//实现方式还可以继承其他类,继承方式不可以再继承其他类了


public static void main(String[] args) {

Runnable buyer = new Buyer();

Thread one = new Thread(buyer);
Thread two = new Thread(buyer);

one.start();
two.start();
}

}

class Buyer implements Runnable{

private int ticket=10;

//指定线程的任务
@Override
public void run() {

while(ticket>0){
System.out.println("当前购买的ticket是:"+ticket);
ticket--; //--ticket;
}
}

}

线程安全

常见概念

  • 线程安全

    多线程修改操作同一份资源数据不会错乱

  • 线程不安全 [线程安全问题]

    多线程修改操作同一份资源带来的数据错乱。

处理方案

  • 同步[监视对象]
    • 同步方法
    • 同步代码块

案例一

同步方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.neu.day11._06safe;

public class _01BuyTicket {

//线程安全处理的方案
//同步 [监视对象]
//同步方法
//
//同步代码块

//锁

//分析为什么有线程安全问题?

public static void main(String[] args) {

Runnable buyer = new Buyer();

Thread one = new Thread(buyer);


Thread two = new Thread(buyer);

one.start();
two.start();
}
}

class Buyer implements Runnable{

private int ticket=10;

//指定线程的任务
@Override
public void run() {
buy();
}


private synchronized void buy(){ //监视对象this,static同步方法的监视对象是 类.class

while(ticket>0){
System.out.println("购买的ticket是:"+ticket);

try {
Thread.sleep(100); //让线程休眠
} catch (InterruptedException e) {
e.printStackTrace();
}

ticket--;
}
}
}

案例二

验证两个资源的监视对象不一样的时候,当线程1进入监视对象1的资源时,线程2是否可以进入监视对象2的资源?

结论可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class _02TestMonitor {

public static void main(String[] args) {

Runnable buyer = new MyBuyer();

Thread one = new Thread(buyer);


Thread two = new Thread(buyer);

one.start();
two.start();
}
}

class MyBuyer implements Runnable{
private boolean sign=true;

//指定线程的任务
@Override
public void run() {

if(sign){
sign=false;
one();
}else{
two();
}
}

private synchronized void one(){ //this

System.out.println("one....");
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

//加上static的监视对象是MyBuyer.class,请问打印的顺序?自行分析。
private synchronized void two(){ //this
System.out.println("two....");
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

案例三

同步代码块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class _03BuyTicket {

//同步方法
//同步代码块
//synchronized(监视对象){
//}

public static void main(String[] args) {

Runnable buyer = new Killer();

Thread one = new Thread(buyer);


Thread two = new Thread(buyer);

one.start();
two.start();
}
}

class Killer implements Runnable{

private int ticket=10;

//指定线程的任务
@Override
public void run() {
buy();
}


private void buy(){
System.out.println("hello");

synchronized (this){ //this
while(ticket>0){
System.out.println("购买的ticket是:"+ticket);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
ticket--;
}
}
}
}

案例四

使用可重入锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class _04BuyApple {

//lock

public static void main(String[] args) {

Runnable buyer = new BuyerApple();

Thread one = new Thread(buyer,"one");
Thread two = new Thread(buyer,"two");

one.start();
two.start();
}

}

class BuyerApple implements Runnable{

private ReentrantLock lock = new ReentrantLock();

private int count=10;

@Override
public void run() {

buy();
}

private void buy(){

try {
lock.lock();
while(count>0){
Thread thread = Thread.currentThread();
System.out.println(thread.getName()+"购买了,苹果编号是:"+count);
count--;
}
} finally {
lock.unlock();
}
}
}

单例

含义

某个类在程序运行期间最多只能创建一个对象

方式

  • 饿汉式

  • 懒汉式

    需要使用的时候才创建对象

  • 枚举

懒汉式

步骤

  • 构造器private

  • 对外提供获取实例的方法

    注意里面要考虑线程安全的问题

代码

ATM.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class ATM {

private static ATM atm;

private ATM(){

}


/*
public synchronized static ATM getInstance(){

if(atm==null){
atm = new ATM();
}
return atm;
}
*/

public static ATM getInstance(){
if(atm==null){
synchronized(ATM.class){
if(atm==null){
atm = new ATM();
}
}
}
return atm;
}
}

Test.java

1
2
3
4
5
6
7
8
9
10
public class Test {

public static void main(String[] args) {
ATM atmOne = ATM.getInstance();
ATM atmTwo = ATM.getInstance();


System.out.println(atmOne==atmTwo);
}
}

常见方法下

  • isAlive
  • setPriority
  • getPriority
  • isInterrupted
  • interrupt

判断是否存活

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class _01isAliveTest {


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

Thread thread = new MyThread();
thread.start();

Thread.sleep(1000);

//判断的是run方法是否执行完
System.out.println(thread.isAlive());//false
}

}

class MyThread extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(i);
}
}
}

线程优先级

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class _02PriorityTest {

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

Thread oneThread = new Thread(){
@Override
public void run() {
System.out.println("one的优先级是"+this.getPriority());
}
};


Thread twoThread = new Thread(){
@Override
public void run() {
System.out.println("two的优先级是"+this.getPriority());
}
};

//System.out.println(Thread.NORM_PRIORITY);

twoThread.setPriority(Thread.MAX_PRIORITY);
oneThread.setPriority(Thread.MIN_PRIORITY);

oneThread.start();
twoThread.start();
}
}

线程中断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class _03InterruptTest {	
//线程的中断
//run方法执行完
//??

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

Thread thread = new NumThread();
thread.start();

Thread.sleep(100);

thread.interrupt(); //只是修改了线程的一个状态
}
}

class NumThread extends Thread{

@Override
public void run() {
for(int i=0;i<100;i++){

if(isInterrupted()){
return;
}

try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i+"是否中断了"+isInterrupted());
}
}
}