• core java 10~12(多线程 & I/O & Network网络编程)


    MODULE 10 Threads 多线程
    --------------------------------

    进程: 计算机在运行过程中的任务单元,CPU在一个时间点上只能执行一个进程,但在一个时间段上采用时间分片原则。

    特点:
    每个进程执行时需要独立的数据空间,独立分配内存,多个进程间的资源互不共享。因此进程是非常耗费资源的


    线程:是程序运行时的最小执行单位


    特点:
    1)线程依赖于进程
    2)一个进程可以分为多个线程 例:QQ
    3)*多线程可以共享资源

    多进程和多线程的设计目的都是为了在同时执行多个任务

    多线程带来的问题:
    多线程间的并发(互斥)与同步,(由共享资源引发的问题)

    线程类Thread

    创建自己的线程
    1.继承Thread类
    class MyThread extends Thread{
    public void run(){
    //线程处理代码
    }
    }
    运用:
    MyThread th1=new MyThread();
    th1.run();//错误
    th1.start();//启动该线程,执行的是run()方法中的代码
    2.实现Runnable接口
    class MyThread implements Runnable{
    public void run(){
    //线程处理代码
    }
    }
    运用:
    MyThread th1=new MyThread();
    th1.start();//错误
    Thread thread=new Thread(th1);
    thread.start();//启动线程,执行的是th1中的run()方法


    练习:
    龟兔猫狗百米赛跑,要求:只要有一个先跑到终点,比赛结束

    分析:设置一个多个线程都共享的数据
    static boolean isRunning=true;


    线程生命周期的状态:
    1.Runnable就绪状态
    new -->start() --> Runnable
    等待JVM调度执行
    2.Running状态
    JVM采取时间分片策略,被调度的线程从Runnable进入Running状态
    执行run()方法中的代码,一旦时间片结束,无论run()方法是否执行完,JVM都会收回该线程的执行权,调度其他处于Runnable状态的线程
    Runnable <-----> Running

    3.Dead死亡状态
    run()方法执行结束

    4.Blocked阻塞状态
    1)sleep() ---> blocked
    等到睡眠时间结束,该线程从bloced ---> Runnable,等待JVM重新调度
    2)join() ---> blocked
    调用另一线程的join()方法,使本线程进入阻塞状态,直到另一线程执行结束,本线程 blocked ---> Runnable


    多线程的并发访问
    ----------------------------------
    多个线程共享数据引发并发问题

    练习:

    如何解决并发访问?
    synchronized关键字
    1)寻找公有的对象,并在公有对象身上加锁,确保一次只能有一个线程操作该对象
    synchronized(Object){
    //只允许一个线程执行这部分代码
    }
    2)精确控制加锁的范围(或者说加锁的临界值),否则影响程序效率


    线程如何从locked回到Runnable状态
    ------------------------------------
    1)sleep 睡眠时间结束,回到Runnable
    2)join() 等到另一线程执行结束,本线程回到Runnable
    3)如何人为使线程从blocked ------> Runnable
    a) interrupt()
    人为使线程从blocked ------> Runnable
    阻塞的线程一旦被调用interrupt()方法唤醒,会抛出InterruptedException,线程自己可以通过捕获该异常知道自己被中断
    b)isInterrupted() 返回boolean类型,判断线程是否被中断
    c)interrupted() 清除中断信息,因为一个线程被中断后会设置标志信息,isInterruped()判断为true,一旦调用interrupted()清除中断信息后,isInterruped()判断改为false

    练习:ThreadState.java , 在主线程中监控另一个线程让该线程sleep后,调用interrupt()方法使其从blocked回到Runnable

    线程同步问题
    -------------------------------------
    并发:是多个线程地位均等,共同竞争对公有对象的访问权,一次只能一个线程访问

    同步:解决的是多个线程对公有对象访问的先后顺序问题

    解决同步问题的思路:
    1)找出公有对象,多个线程都通过公有对象进行通信
    2)找出哪个线程该wait,哪个线程负责notify发通知
    3)确保wait在notify之前
    添加标志变量hasWait,等待的线程在调用wait()之前设置该变量,负责发通知的线程在notify()之前先判断该变量,确保notify时公有对象身上已经有wait的线程


    练习:
    定义一个线程CalculateThread,计算1~100的和,把结果放到一个对象中
    定义一个线程PrintThread,从该对象中取出结果并打印输出
    定义一个测试程序Test.java

    分析:
    1)属于同步问题
    2)公有对象Result{int value;}
    3)CalculateThread负责notify,PrintThread负责wait


    注意点:
    1.wait()和notify()要加synchronized
    多个线程竞争公有对象res的访问锁,等待的线程间要互斥
    2.等待的线程在wait之前要先设置标志变量,否则wait之后阻塞,无法设置
    3.发通知的线程在notify之前要循环判定公有对象身上是否有等待的线程,有wait线程才发通知唤醒
    4.while循环一定要放synchronized外面,否则拿着锁再sleep,其他线程永远拿不到res对象的访问权

    setPriority() 设置线程的优先级 1~10级 优先级并不能决定线程的先后执行顺序,最终仍由JVM决定

    Thread.yield() 将执行权让给优先级比自己高的线程

    弃而不用的方法:
    stop() / resume() / suspend()
    这些方法被调用时,线程所占据的资源的锁不会被释放


    死锁问题
    ------------------------------
    若干线程去竞争有限的资源,要求同时拿到多个公有资源时,因公有资源数量有限,不能满足所有线程的需求,每个线程都只拿到部分资源且不释放,就造成死锁问题

    哲学家就餐问题

    如何解决?
    让多个竞争资源的线程以相同的顺序去拿

    MODULE 11 I/O 输入/输出
    ------------------------------------
    java中采取流的概念, 在应用程序和外围设备之间建立一个流对象,确保无论外围设备是什么,应用程序只单一的通过访问流对象来读写数据

    按流的方向,分为:
    输入流InputStream
    程序从输入流【读取】数据,但不能写入
    read()...
    输出流OutputStream
    程序往输出流中【写入】数据,但不能读取
    write()...

    按照流的传输单位
    字节流
    以字节为基本传输单位,一个个字节传输
    注意点:
    1)流中的数据没有结构,例int数据4个字节,拆成4次传输
    2)最终传输给外围设备的一定是字节流
    通常以Stream结尾的都是字节流*

    字符流
    字节的可读性很差,字符流提供以文本的形式读写数据
    通常带有Reader/Writer的都是字符流*

    具有缓存功能的流
    在流对象中设置缓存区,数据先放入缓存区,再一次性读写外围设备
    目的:提高数据的传输性能

    过滤器
    对流中提供的数据进行进一步处理
    字节流传输无结构,过滤器可以将字节流中的字节拼成应用程序需要的数据类型,如int double float...
    *不能单独使用,一定要结合某个字节流


    InputStream常见的方法
    read() 每次返回一个字节,返回结果>=0为有效数据, -1表示流中数据读完
    read(byte[]) 可以一次读取多个字节,放入byte[]数组中,返回一次读取成功的字节数

    注意:
    I/O流要与外围设备进行交互,所有资源都要手工回收
    finally{
    //添加资源回收代码
    }

    close() 关闭流对象,释放内存资源
    available() 判断流是否可用

    flush() 程序强制将缓存区中的数据刷新到外围设备中

    字节流的层级结构
    -------------------------
    通常InputStream/OutputStream 前面的代表了数据源或数据目的地类型
    FileInputStream 把文件作为数据源,从文件中读数据
    FileOutputStream 把文件作为数据目的地,往文件中写入数据

    PipedInputStream 把管道作为数据源
    PipedOutputStream 把管道作为数据目的地

    过滤器 对字节流进一步包装
    1)BufferedInputStream
    具有缓存功能的流
    2)PushbackInputStream
    把从流中读取的数据退回去
    3)DataInputStream
    能够将字节流中的字节拼成程序需要的基本数据类型
    readInt(0 readDouble()...

    包: java.io;
    异常: IOException

    练习:创建类Copy.java实现文件的拷贝
    将一个文件的内容拷贝到另一文件

    分析:从源文件读入数据,FileInputStream read()
    写入目标文件 FileOutputStream write()


    改造:以提高性能的方式


    例:以提高性能的方式从指定文件啊src.txt中读取含有基本数据类型的内容

    分析:
    DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream("src.txt")));

    练习:将一个int型整数写入文件中
    1)将一个个字节传输,将int拆成4个字节
    2)DataOutputStream(BufferedOutputStream(FileOutputStream))


    管道流PipedInputStream/PipedOutputStream
    -----------------------------------------------
    PipedInputStream 从管道中读取数据
    PipedOutputStream 往管道中写入数据
    通过管道将输入流和输出流衔接起来

    练习:
    创建两个线程,通过管道流实现两个线程的数据传输
    一个线程Sender负责产生100个随机数,并写入管道中
    一个线程Fetcher负责从管道中读取数据,并打印输出

    分析; class Sender extends Thread{
    PipedOutputStream pos;
    public void run(){}
    }
    class Fetcher extends Thread{
    PipedInputStream pis;
    public void run(){}
    }


    字符流Reader/Writer
    ------------------------------
    字节流可读性差,字符流提供以文本形式传输数据

    特别的流对象
    1.BufferedrReader/BufferedWriter
    1)开辟缓存区提高传输性能
    类似BufferedInputStream(BIS)/BOS
    2)提供字符流和字符串之间的转换
    类似DIS/DOS
    BufferedReader: readLine() 字符流--->字符串
    BUfferedWriter: write(String,off,len) 字符串---->字符流

    2.InputStreamReader/OutputStreamWriter 桥梁类
    最终与外围设备交互的是字节流
    1)提供字节流和字符流之间的转换
    InputStreamReader:字节流-----> 字符流
    OutputstreamWriter:字符流----> 字节流
    2)提供java标准编码UTF8和其他编码之间的转换

    3.FileReader/FileWriter 是InputStreamReader/OutputStreamWriter的子类
    1)具有读写文件的功能
    2)作为ISR/OSW的子类,也提供字节流和字符流之间的转换
    3)将编码自动转换成操作系统对应的编码格式

    练习:
    将一个字符串写入文件中,再读取该文件并将内容输出到控制台

    分析:
    字符串 --->文件
    字符串----> 字符流 BuffredWriter
    字符流 字节流 OutputStreamWriter FileWriter
    字节流 文件 FileOutputStream
    文件-----> 控制台

    System.out 标准输出
    System.in 键盘
    System.err 标准错误


    对象序列化 ObjectInputStream/ObjectOutputStream
    ------------------------------------------------------------
    序列化:将对象转化为字节流,通常用于保存对象 的当前状态信息
    使对象持久化,以备将来对该对象进行恢复
    反序列化:字节流-----> Object

    ObjectInputStream: Object readObject(){} 反序列化
    ObjectOutputStream: writeObject(Object) 序列化

    序列化实现接口:
    Serializable

    class Company implements Serializable{
    String name;
    int tel;
    transient Address add; //标注该属性信息无法序列化
    }
    class Address{
    String city;
    String street;
    int no;
    }

    注意:
    1)大对象中包含小对象,序列化时要求小对象也实现了序列化接口
    2)对于不能序列化的属性,需要用transient修饰

    练习:ObjectTest.java


    RandomAccessFile随机访问文件
    -----------------------------------
    以随机访问的方式读写文件中任意一段内容

    skip(long) 虽是跳步,但也是从头开始跳过若干字节再进行读写

    功能:
    1)实现了DataInput / DataOutput接口,类似过滤器
    2)读/写功能都具有
    readInt() writeInt()......
    3)具有操作文件的功能
    4)可以随意跳到文件的某个位置开始读写

    构造器中的参数:
    mode 指定读/写的模式
    "r":只读 "r":只写 "rw":读/写

    seek(long) 跳过long 指定的若干字节数,开始读写


    MODULE 12 Network网络编程
    --------------------------------
    ip地址 通过IP地址可以唯一定位到网络上的某台机器
    port端口:人为制造的数字,代表一个服务器上某个应用的唯一标识

    基于TCP/IP网络编程
    传输控制协议,考虑的是传输的可靠性问题
    基于UDP的网络编程
    用户数据报文协议,考虑的是传输的效率问题

    通讯双方满足的五要素:
    1.通讯双方IP地址(两个)
    2.通讯双方的PORT端口号(两个)
    3.通讯双方要遵守同样的协议

    java.net包:
    Socket/SeverSocket:实现基于TCP/IP网络编程
    DatagramSocket/DatagramPacket:为UDP协议服务

    IP网络层
    基本特点:
    无连接的;数据可靠性不能保证的;

    TCP 传输层
    1)面向连接的
    2)完全可靠的数据传输
    3)点对点的
    4)同一连接既可以发送也可以接收
    5)面向字节流的

    连接的简历经过了三次握手:
    1)客户端发出连接请求
    2)服务器回复确认
    3)建立连接


    Client:
    构建Socket,连接指定的IP和port
    ---> 获取输入流/输出流
    --> 对I/O流进行包装
    ---->读/写数据
    -->释放资源(Socket/I/O)

    Server:
    构建SeverSocket,指定监听的端口号
    --->接收客户端连接请求,获取Socket建立连接
    ----> 对I/O流进行包装
    ---->读/写数据
    -->释放资源(sevrverSocket/Socket/I/O)


    PrintWriter功能
    String-->字节流
    BufferedWriter 字符串-->字符流
    OutputStreamWriter 字符流--->字节流
    1.字符串--->字节流
    兼具了BufferedWriter/OutputStreamWriter两者的功能
    2.可以自动刷新
    new PrintWriter(OS,true);


    UDP 用户数据报文协议
    -------------------------------------------
    1)考虑的是数据传输的效率问题,可靠性不保证
    2)不一定是一对一,而是多对多通讯,如广播
    3)无连接的,不可靠的传输方式

    DatagramSocket 负责数据的发送和接受 如邮递员
    DatagramPacket 把数据打成报文对象,填入对方的IP地址和端口号 如信件

    构造器:
    DatagramPacket()


    你要坚强,坚强的足以认识自己的弱点;你要勇敢,勇敢的足以面对自己的恐惧;你要堂堂正正。在遇到挫折时能够昂首而不背躬屈膝;你要能够面对掌声,在胜利时能够谦逊而不趾高气扬。真正的伟大直率真诚,真正的贤人虚怀若谷,真正的强者温文尔雅。——萨利·布什(林肯的继母教育林肯)
  • 相关阅读:
    Excel用FREQUENCY统计数值的在指定区间内出现频率
    vim 中的 使用进阶
    sed 处理 多个文件的问题
    在 centos6.4 上编译 mysql 源代码安装数据库
    hadoop 上跑 python job 引入 第三方依赖的解决办法
    关于hadoop的学习笔记
    Gcc的一些参数说明
    makefile 的一些常识
    哈希表

  • 原文地址:https://www.cnblogs.com/jinhuazhe2013/p/4148009.html
Copyright © 2020-2023  润新知