A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© TTwawa 初级黑马   /  2018-12-19 22:24  /  764 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

1,获取线程的名称:
        1.使用Thread类中的方法getName()
        getName() 返回该线程的名称。
        2.可以先获取到当前正在执行的线程,使用线程中的方法getName()获取线程的名称
            Thread.currentThread() 返回对当前正在执行的线程对象的引用。
2,  Thread.sleep(long millis):使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
    毫秒数结束之后,线程继续执行
3,创建多线程程序的第二种方式:实现Runnable接口
    java.lang.Runnable
        Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。
    java.lang.Thread类的构造方法
        Thread(Runnable target) 分配新的 Thread 对象。
        Thread(Runnable target, String name) 分配新的 Thread 对象。

    实现步骤:
        1.创建一个Runnable接口的实现类
        2.在实现类中重写Runnable接口的run方法,设置线程任务
        3.创建一个Runnable接口的实现类对象
        4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        5.调用Thread类中的start方法,开启新的线程执行run方法

    实现Runnable接口创建多线程程序的好处:
        1.避免了单继承的局限性
            一个类只能继承一个类(一个人只能有一个亲爹),类继承了Thread类就不能继承其他的类
            实现了Runnable接口,还可以继承其他的类,实现其他的接口
        2.增强了程序的扩展性,降低了程序的耦合性(解耦)
            实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(解耦)
            实现类中,重写了run方法:用来设置线程任务
            创建Thread类对象,调用start方法:用来开启新线程
4, 匿名内部类方式实现线程的创建

    匿名:没有名字
    内部类:写在其他类内部的类

    匿名内部类作用:简化代码
        把子类继承父类,重写父类的方法,创建子类对象合一步完成
        把实现类实现类接口,重写接口中的方法,创建实现类对象合成一步完成
    匿名内部类的最终产物:子类/实现类对象,而这个类没有名字

    格式:
        new 父类/接口(){
            重复父类/接口中的方法
5, 解决线程安全问题的一种方案:使用同步代码块
    格式:
        synchronized(锁对象){
            可能会出现线程安全问题的代码(访问了共享数据的代码)
        }

    注意:
        1.通过代码块中的锁对象,可以使用任意的对象
        2.但是必须保证多个线程使用的锁对象是同一个
        3.锁对象作用:
            把同步代码块锁住,只让一个线程在同步代码块中执行
6,解决线程安全问题的二种方案:使用同步方法
    使用步骤:
        1.把访问了共享数据的代码抽取出来,放到一个方法中
        2.在方法上添加synchronized修饰符

    格式:定义方法的格式
    修饰符 synchronized 返回值类型 方法名(参数列表){
        可能会出现线程安全问题的代码(访问了共享数据的代码)
  静态的同步方法
        锁对象是谁?
        不能是this
        this是创建对象之后产生的,静态方法优先于对象
        静态方法的锁对象是本类的class属性-->class文件对象(反射)
7,
    解决线程安全问题的三种方案:使用Lock锁
    java.util.concurrent.locks.Lock接口
    Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。
    Lock接口中的方法:
        void lock()获取锁。
        void unlock()  释放锁。
    java.util.concurrent.locks.ReentrantLock implements Lock接口


    使用步骤:
        1.在成员位置创建一个ReentrantLock对象
        2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
        3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁
8, Obejct类中的方法
    void wait()
          在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
    void notify()
          唤醒在此对象监视器上等待的单个线程。
          会继续执行wait方法之后的代码
9, 进入到TimeWaiting(计时等待)有两种方式
    1.使用sleep(long m)方法,在毫秒值结束之后,线程睡醒进入到Runnable/Blocked状态
    2.使用wait(long m)方法,wait方法如果在毫秒值结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入到Runnable/Blocked状态

    唤醒的方法:
         void notify() 唤醒在此对象监视器上等待的单个线程。
         void notifyAll() 唤醒在此对象监视器上等待的所有线程。
1,线程间通信
     等待唤醒机制三个方法:
        wait();放弃cup的执行权
        notify();
        notifyAll();
     wait和notify必须是相同的锁!
2,Lambda表达式(简化代码)
     只有函数式接口才能够使用(只有一个抽象方法)
     格式:(参数列表)->{一些重写方法的代码}
     Lambda表达式可省略的内容:
        1,(参数列表):括号中参数列表的数据类型,可以省略不写
        2,(参数列表):括号中的参数如果只有一个,那么类型和()都可以省略
        3,{一些代码}:如果{ }中的代码只有一行,无论是否有返回值,都可以省略{};return;分号
        注意:要省略{},return,分号必须一起省略
   
3,线程池:JDK1.5之后提供的
    java.util.concurrent.Executors:线程池的工厂类,用来生成线程池
    Executors类中的静态方法:
        static ExecutorService newFixedThreadPool(int nThreads) 创建一个可重用固定线程数的线程池
        参数:
            int nThreads:创建线程池中包含的线程数量
        返回值:
            ExecutorService接口,返回的是ExecutorService接口的实现类对象,我们可以使用ExecutorService接口接收(面向接口编程)
    java.util.concurrent.ExecutorService:线程池接口
        用来从线程池中获取线程,调用start方法,执行线程任务
            submit(Runnable task) 提交一个 Runnable 任务用于执行
        关闭/销毁线程池的方法
            void shutdown()
    线程池的使用步骤:
        1.使用线程池的工厂类Executors里边提供的静态方法newFixedThreadPool生产一个指定线程数量的线程池
        2.创建一个类,实现Runnable接口,重写run方法,设置线程任务
        3.调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法
        4.调用ExecutorService中的方法shutdown销毁线程池(不建议执行)     
1,File类:
        文件和目录路径名的抽象表现形式。
    java把电脑中的文件和文件夹(目录)封装为了一个File类,我们可以使用File类对文件和文件夹进行操作
    File类是一个与系统无关的类,任何的操作系统都可以使用这个类中的方法
    重点:记住这三个单词
        file:文件
        directory:文件夹/目录
        path:路径
File parent = new File("c:\\");
File file = new File(parent,"hello.java");
        String getAbsolutePath() :返回此File的绝对路径名字符串。
        String getPath() :将此File转换为路径名字符串。(toString方法调用的就是getPath方法)
        String getName()  :返回由此File表示的文件或目录的名称。
        long length()  :返回由此File表示的文件的长度。(如果构造方法中给出的路径不存在,那么length方法返回0)
        boolean exists() :此File表示的文件或目录是否实际存在。
        boolean isDirectory() :此File表示的是否为目录。
        boolean isFile() :此File表示的是否为文件。( 这两个方法使用前提,路径必须是存在的,否则都返回false)
        boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
        boolean delete() :删除由此File表示的文件或目录。
        boolean mkdir() :创建由此File表示的目录。
        boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。
        String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录。
        File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录。
2,递归:方法自己调用自己
    - 递归的分类:
      - 递归分为两种,直接递归和间接递归。
      - 直接递归称为方法自身调用自己。
      - 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
    - 注意事项:
      - 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
      - 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
      - 构造方法,禁止递归
    递归的使用前提:
        当调用方法的时候,方法的主体不变,每次调用方法的参数不同,可以使用递归
3,过滤文件
        在File类中有两个和ListFiles重载的方法,方法的参数传递的就是过滤器
    File[] listFiles(FileFilter filter)
    java.io.FileFilter接口:用于抽象路径名(File对象)的过滤器。
        作用:用来过滤文件(File对象)
        抽象方法:用来过滤文件的方法
            boolean accept(File pathname) 测试指定抽象路径名是否应该包含在某个路径名列表中。
            参数:
                File pathname:使用ListFiles方法遍历目录,得到的每一个文件对象
    File[] listFiles(FilenameFilter filter)
    java.io.FilenameFilter接口:实现此接口的类实例可用于过滤器文件名。
        作用:用于过滤文件名称
        抽象方法:用来过滤文件的方法
            boolean accept(File dir, String name) 测试指定文件是否应该包含在某一文件列表中。
            参数:
                File dir:构造方法中传递的被遍历的目录
                String name:使用ListFiles方法遍历目录,获取的每一个文件/文件夹的名称
    注意:
        两个过滤器接口是没有实现类的,需要我们自己写实现类,重写过滤的方法accept,在方法中自己定义过滤的规则
File[] files = dir.listFiles(pathname->pathname.isDirectory() || pathname.getName().toLowerCase().endsWith(".java"));
  过滤的规则:
            在accept方法中,判断File对象是否是以.java结尾
            是就返回true
            不是就返回false
            如果pathname是一个文件夹,返回true,继续遍历这个文件夹
1, FileOutputStream 文件字节输出流:
        close() :关闭此输出流并释放与此流相关联的任何系统资源。
        flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
        write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
        write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
        write(int b) :将指定的字节输出流。
        写入数据的原理(内存-->硬盘)
        java程序-->JVM(java虚拟机)-->OS(操作系统)-->OS调用写数据的方法-->把数据写入到文件中
    字节输出流的使用步骤(重点):
        1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
        2.调用FileOutputStream对象中的方法write,把数据写入到文件中
        3.释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序的效率)
        追加写/续写:使用两个参数的构造方法
        FileOutputStream(String name, boolean append)创建一个向具有指定 name 的文件中写入数据的输出文件流。
        FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
        参数:
           String name,File file:写入数据的目的地
           boolean append:追加写开关
            true:创建对象不会覆盖源文件,继续在文件的末尾追加写数据
            false:创建一个新文件,覆盖源文件
    写换行:写换行符号
        windows:\r\n("\r\n".GetBytes)
        linux:/n
        mac:/r
2,FileInputStream:文件字节输入流
        定义了所有子类共性的方法:
        read()从输入流中读取数据的下一个字节。
        read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
        close() 关闭此输入流并释放与该流关联的所有系统资源。
        读取数据的原理(硬盘-->内存)
        java程序-->JVM-->OS-->OS读取数据的方法-->读取文件

    字节输入流的使用步骤(重点):
        1.创建FileInputStream对象,构造方法中绑定要读取的数据源
        2.使用FileInputStream对象中的方法read,读取文件
        3.释放资源
         发现以上读取文件是一个重复的过程,所以可以使用循环优化
            不知道文件中有多少字节,使用while循环
            while循环结束条件,读取到-1的时候结束

            布尔表达式(len = fis.read())!=-1
                1.fis.read():读取一个字节
                2.len = fis.read():把读取到的字节赋值给变量len
                3.(len = fis.read())!=-1:判断变量len是否不等于-1
3, FileReader:文件字符输入流
         共性的成员方法:
         read() 读取单个字符并返回。
        read(char[] cbuf)一次读取多个字符,将字符读入数组。
         close() 关闭该流并释放与之关联的所有资源。
4,FileWriter:文件字符输出流
        共性的成员方法:
         write(int c) 写入单个字符。
         write(char[] cbuf)写入字符数组。
         write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
         write(String str)写入字符串。
         write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
         flush()刷新该流的缓冲。
         close() 关闭此流,但要先刷新它。
flush方法和close方法的区别
        - flush :刷新缓冲区,流对象可以继续使用。
        - close:  先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
        字符输出流写数据的其他方法
        write(char[] cbuf)写入字符数组。
         write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
         write(String str)写入字符串。
         write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
5,try catch finally
    JDK7的新特性
    在try的后边可以增加一个(),在括号中可以定义流对象
    那么这个流对象的作用域就在try中有效
    try中的代码执行完毕,会自动把流对象释放,不用写finally
    格式:
        try(定义流对象;定义流对象....){
            可能会产出异常的代码
        }catch(异常类变量 变量名){
            异常的处理逻辑
6, Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。
       Properties集合是一个唯一和IO流相结合的集合
        可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
        可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用

    属性列表中每个键及其对应值都是一个字符串。
        Properties集合是一个双列集合,key和value默认都是字符串
  使用Properties集合存储数据,遍历取出Properties集合中的数据
        Properties集合是一个双列集合,key和value默认都是字符串
        Properties集合有一些操作字符串的特有方法
         setProperty(String key, String value) 调用 Hashtable 的方法 put。
         getProperty(String key) 通过key找到value值,此方法相当于Map集合中的get(key)方法
        Set<String> stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,此方法相当于Map集合中的keySet方法       
        tips1:
         可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
        void store(OutputStream out, String comments)
        void store(Writer writer, String comments)
        参数:
            OutputStream out:字节输出流,不能写入中文
            Writer writer:字符输出流,可以写中文
            String comments:注释,用来解释说明保存的文件是做什么用的
                    不能使用中文,会产生乱码,默认是Unicode编码
                    一般使用""空字符串

        使用步骤:
            1.创建Properties集合对象,添加数据
            2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
            3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
            4.释放资源
        ex:prop.store(new FileOutputStream("09_IOAndProperties\\prop2.txt"),"");
        tips2:
        可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用
        void load(InputStream inStream)
        void load(Reader reader)
        参数:
            InputStream inStream:字节输入流,不能读取含有中文的键值对
            Reader reader:字符输入流,能读取含有中文的键值对
        使用步骤:
            1.创建Properties集合对象
            2.使用Properties集合对象中的方法load读取保存键值对的文件
            3.遍历Properties集合
        注意:
            1.存储键值对的文件中,键与值默认的连接符号可以使用=,空格(其他符号)
            2.存储键值对的文件中,可以使用#进行注释,被注释的键值对不会再被读取
            3.存储键值对的文件中,键与值默认都是字符串,不用再加引号
1,BufferedOutputStream:字节缓冲输出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("10_IO\\a.txt"));
2, BufferedInputStream:字节缓冲输入流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("10_IO\\a.txt"));
3,BufferedWriter:字符缓冲输出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("10_IO\\c.txt"));
特有的成员方法:
        void newLine() 写入一个行分隔符。会根据不同的操作系统,获取不同的行分隔符
4,BufferedReader:字符缓冲输入流
         BufferedReader br = new BufferedReader(new FileReader("10_IO\\c.txt"));
特有的成员方法:
        String readLine() 读取一个文本行。读取一行数据
            行的终止符号:通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行(\r\n)。
5,OutputStreamWriter: 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。(编码:把能看懂的变成看不懂)
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("10_IO\\gbk.txt"),"GBK");
不指定默认使用UTF-8
6, InputStreamReader:是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。(解码:把看不懂的变成能看懂的)
         InputStreamReader isr = new InputStreamReader(new FileInputStream("10_IO\\gbk.txt"),"GBK");
7, ObjectOutputStream:对象的序列化流
    作用:把对象以流的方式写入到文件中保存
         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("10_IO\\person.txt"));
                  使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
                  oos.writeObject(new Person("小美女",18));
8,ObjectInputStream:对象的反序列化流
    作用:把文件中保存的对象,以流的方式读取出来使用
readObject方法声明抛出了ClassNotFoundException(class文件找不到异常)
     当不存在对象的class文件时抛出此异常
     反序列化的前提:
        1.类必须实现Serializable
        2.必须存在类对应的class文件
         ObjectInputStream ois = new ObjectInputStream(new FileInputStream("10_IO\\person.txt"));
        使用ObjectInputStream对象中的方法readObject读取保存对象的文件
        Object o = ois.readObject();
         释放资源
        ois.close();
        使用读取出来的对象(打印)
        System.out.println(o);
        Person p = (Person)o;
9, PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
PrintStream特点:
        1.只负责数据的输出,不负责数据的读取
        2.与其他输出流不同,PrintStream 永远不会抛出 IOException
        3.有特有的方法,print,println
            void print(任意类型的值)
            void println(任意类型的值并换行)
注意:
        如果使用继承自父类的write方法写数据,那么查看数据的时候会查询编码表 97->a
        如果使用自己特有的方法print/println方法写数据,写的数据原样输出 97->97
         PrintStream ps = new PrintStream("10_IO\\print.txt");
        //如果使用继承自父类的write方法写数据,那么查看数据的时候会查询编码表 97->a
        ps.write(97);
        //如果使用自己特有的方法print/println方法写数据,写的数据原样输出 97->97
        ps.println(97);
使用System.setOut方法改变输出语句的目的地改为参数中传递的打印流的目的地
        static void setOut(PrintStream out)
          重新分配“标准”输出流。
=====================================
System.out.println("我是在控制台输出");
        PrintStream ps = new PrintStream("10_IO\\目的地是打印流.txt");
        System.setOut(ps);//把输出语句的目的地改变为打印流的目的地
        System.out.println("我在打印流的目的地中输出");
1,软件结构:
        c/s结构:客户端和服务器结构
        b/s结构:浏览器和服务器结构
2,网络通信协议:
        TCP:传输控制协议。需连接服务器(三次握手,保证传输的可靠性)
        UDP:面向无连接的协议,传输速度快,有可能会丢包
3,编程三要素:
        协议     IP地址   端口号
4,Socket类
         Socket socket = new Socket("127.0.0.1",8888);
        网络字节流(传输):OutputStream os = socket.getOutputStream();
5,ServerSocket类
        ServerSocket server = new ServerSocket(8888);
        Socket socket = server.accept();
6,文件上传案例的客户端:读取本地文件,上传到服务器,读取服务器回写的数据
         void shutdownOutput() 禁用此套接字的输出流。
            对于 TCP 套接字,任何以前写入的数据都将被发送,并且后跟 TCP 的正常连接终止序列。
7,文件上传案例服务器端:读取客户端上传的文件,保存到服务器的硬盘,给客户端回写"上传成功"
        让服务器一直处于监听状态(死循环accept方法)
                    有一个客户端上传文件,就保存一个文件
       
                使用多线程技术,提高程序的效率
                有一个客户端上传文件,就开启一个线程,完成文件的上传
        自定义一个文件的命名规则:防止同名的文件被覆盖
                        规则:域名+毫秒值+随机数
7, 创建BS版本TCP服务器
        把is网络字节输入流对象,转换为字符缓冲输入流
                 BufferedReader br = new BufferedReader(new InputStreamReader(is));
                 把客户端请求信息的第一行读取出来

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马