day24周日休息_chap-Thread_1.多线程实现方式2.锁3.网络编程(本篇多线程)

本周学习了多线程、数据安全锁、网络通信编程

这篇记录多线程

开篇留一个问题:线程中sleep方法的作用是让当前线程暂停,其他线程继续,还是就是仅仅暂停

答:

sleep方法让线程暂停的意义是等待控制台输入信息,进行操作的变更(idea中直观的感受);

或者线程切换

一.多线程的实现3种方法

线程的启动:都是调用start方法,调用具体的run方法并不是启动线程

线程的功能:run方法中的语句就是线程中具体的操作,开一个线程为了做什么都写在run方法中

(方法1)重写Thread类的run方法:可以直接用匿名对象的方式,创建对象,后面用lambda表达式写抽象方法run的具体实现

(方法2)重写Runnable接口的run方法:还是需要创建线程对象,这个线程对象构造参数传入的是一个接口对象,这个接口实现的抽象父接口叫Runnable,同时实现的父接口抽象方法还是叫run(),所以创建线程之后,还是用线程对象调用.start()方法来启动线程

这里引入数据安全问题,解决办法是用锁,两种:

synchronized代码块

->对象:必须是同一个对象,必须有名字(不能直接写new创建匿名对象)

->代码块:this关键字指向的对象

->静态方法:字节码文件,一般是类名.class,比如自己用来实现Runnable接口的子接口名是MyRunnable,那么synchronized括号里面参数就写MyRunnable.class

Lock类调用ReentrantLock构造方法创建对象然后调用lock和unlock方法

 

之后因为使用两次嵌套synchronized关键字引入死锁现象

问题描述:定义了对象类,充当锁对象括号内的参数,但是有两个,两个实现Runnable接口的子接口对象,继续创建出对应的线程对象

然后调用启动方法,产生死锁

->解决办法1:更改加锁顺序。如果加锁逻辑在if分支中不一样,就修改成一样的嵌套顺序。原因未知,自己还没理解

->解决办法2:再加一个锁对象,锁之前的if分支,使得两个分支被同一个对象锁操作

(方法3)重写Callable接口的call方法

这篇记录只是大纲,代码其实需要自己运行添加解读注释,还需要深入理解

目前突然想到的薄弱记忆点:

深度克隆和浅克隆:涉及内部类的复制问题

文件流的操作:

1.创建文件是用文件名还是全地址?点斜杠文件名表示相对目录创建可以在idea项目同级根目录直接看见,直接在idea界面查看

2.字节流读取、写回:

官方定义是输入输出,但是自己理解如下:

输入:从文件读取到内存,等价于读取字符串输出到控制台。当然这个是在idea自己看见的一般形式

输出:从内存写回到文件,等价于把赋值结束后的【字节数组或者字符行】作为参数用write方法输出到文件

目前严重混淆的是一个创建对象的嵌套调用形式:连续两个new方法嵌套,为了一步完成创建字节流或者字符流的输入输出流

这样对于输出流要添加append关键字不好明确位置,需要自己从最内层找到文件基础流,然后写逗号true

但是可以明确:外层到内层的嵌套,其实是一个子类构造方法,传入的参数是父类继续调用构造方法,父类继续调用最基础的文件对象创建方法

下面是一些见到的代码例子:括号外是子类,括号内是父类,最内层的是文件对象

<1>

缓冲字符流(字节字符转换流(文件对象))

package com.cskaoyan.tcp.v2;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @description:
 * @author: 景天老师
 **/

public class Server2 {
    public static void main(String[] args) throws Exception{
        //【1.】创建服务端Serversocket对象,指定自己的通信端口 11111
        ServerSocket serverSocket = new ServerSocket(11111);

        while (true) {
            //为什么这里不用字节数组,因为是字符流,我们在控制台输入汉字
            //byte[] bytes = new byte[1024];
            //int readCount = in.read(bytes);
            //String s = new String(bytes, 0, readCount);
            //【2.】监听连接请求
            //服务器端套接字一直用自己的 11111 端口监听
            //监听到请求,就创建客户端套接字对象,存储监听到的套接字,后面调用套接字方法
            Socket socket = serverSocket.accept();//之后用这个客户端套接字来调用收发

            //【3.】用客户端套接字调用返回输入流方法,是服务器端读客户端内容到这个流
            InputStream in = socket.getInputStream();

            //最内层是字节向字符转换
            //外层是缓冲字符流
            //需要理解这种嵌套定义的父类子类关系:
            //缓冲字符流,为了用读取行方法。参数是套接字返回的输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            //字符串变量s接收读取到的行,向服务器端输入
            String s = br.readLine();
            //返回客户端ip地址字符串
            InetAddress inetAddress = socket.getInetAddress();
            //返回客户端通信端口
            int port = socket.getPort();
            //【4.】拼接信息字符串
            System.out.println("接收到了来自" + inetAddress + ":" + port + "的消息: " + s);
        }

    }
}

<2>

缓冲字符流(文件字符流(文件名))

package com.cskaoyan.buffer;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @description:
 * @author: songtao@cskaoyan.onaliyun.com
 **/

public class Demo {
    public static void main(String[] args) throws IOException {
        //创建缓冲输出流
        //BufferedWriter,用Writer是字符,
        //在这里BufferedWriter的参数是新建了FileWriter字符流输出流对象
        //一个char数组,默认大小8192,总计16kB
        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
        bw.write("选择正确");
        //除了Writer的5种方法,新增加了newLine()换行方法
        bw.newLine();
        bw.write("才是正确");
        bw.close();
    }
}

<3>

字节字符转换流(文件字符流(文件名))

package com.cskaoyan.bytestream.transf;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/**
 * @description: 转换流
 * @author: 景天老师
 **/

public class Demo {
    public static void main(String[] args) throws IOException {
        //创建转化输出流对象
        //【字符】
        OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("a.txt"));
        //写数据
        String s = "今日进度:校对需求文档大纲";
        //writeSingle(out, s);

        //多字符
        //writeMuti(out, s);

        //直接写字符串
        out.write(s,0,s.length());

        String encoding = out.getEncoding();//获取输出流的编码
        System.out.println(encoding);

        out.flush();
        //close
        out.close();
    }

    private static void writeMuti(OutputStreamWriter out, String s) throws IOException {
        char[] chars = s.toCharArray();//转String到字符数组
        out.write(chars,0,chars.length);
    }

    private static void writeSingle(OutputStreamWriter out, String s) throws IOException {
        char[] chars = s.toCharArray();//为了对比,所以写成for循环,每个字符数组元素作为参数
        for (int i = 0; i < chars.length; i++) {
            out.write(chars[i]);
        }
    }
}

<4>

字节字符转换流(文件字节输出流(文件名),charsetName)

可以指定字符集的:文件字节流,而且是读取

package com.cskaoyan.bytestream.transf;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @description: 转换流读取数据
 * @author: 景天老师
 **/

public class Demo2 {
    public static void main(String[] args) throws IOException {
        // 创建转换输入流
        InputStreamReader in = new InputStreamReader(new FileInputStream("a.txt"));
        InputStreamReader in2 = new InputStreamReader(new FileInputStream("a1.txt"), "GBk");
        // 读取数据
        int readData1 = in.read();
        System.out.println(((char) readData1));
        //readSingle(in);

        // 读取多个字符 读取的字符数,如果已到达流的末尾,则返回 -1
        char[] chars = new char[1024];//读取输入流in内容到chars字符数组
        int readCount1;//表示读取到的字符个数
        while ((readCount1 = in.read(chars)) != -1) {
            System.out.println(new String(chars,0,readCount1));
        }
        //readMuti(in);

        in.close();
    }

    private static void readMuti(InputStreamReader in) throws IOException {
        char[] chars = new char[1024];//读取输入流in内容到chars字符数组
        int readCount;
        while ((readCount = in.read(chars)) != -1) {
            System.out.println(new String(chars,0,readCount));
        }
    }

    private static void readSingle(InputStreamReader in) throws IOException {
        int readData = in.read();
        System.out.println(((char) readData));
        int readData2 = in.read();
        System.out.println(((char) readData2));
        int readData3 = in.read();
        System.out.println(((char) readData3));
        int readData4 = in.read();
        //System.out.println(((char) readData4));//换行
        System.out.println(readData4);
        //System.out.println((char)13);
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值