走进Java 4

多线程

线程依赖于进程而存在
        线程:  能够执行的最小单元
        进程:能够调用系统资源的独立单位(电脑任务管理器,可以看到进程状态)
        多进程:计算机都是支持多进程的,就是提高CPU的使用率
                    开启多进程时,打游戏,听歌,看网页并不是在同时进行,而是一点时间片在两个进程之间高效切换,时间非常短,会误以为是同时进行
        多线程的意义:多个线程在互相抢占CPU的执行权     线程的执行具有随机性

       Jvm是多线程吗?
              是一个多线程,至少有两条线程   main 主线程也叫用户线程   gc 垃圾回收器,开启垃圾回收器,用来回收没有更多有需要的对象
       面试题:
                  Java能直接创建多线程吗?
                           不能   因为创建线程需要创建进程,需要使用系统资源创建进程,java是不能够直接操作系统资源的,底层语言c是可以操作系统的
                           jdk提供了Thread类,里面有一个start(),然后才可以执行线程,底层也是非java语言实现的
       线程Thread的状态:
                NEW新建  RUNNABLE运行   BLOCKED阻塞   WATING 死死等待   TIME_WAITING超时等待   TERMINATED终止死亡
       线程优先级:
               MAX_PRIORITY 10    最大优先级
               NORM_PRIORITY 5    默认优先级
               MIN_PRIORITY 1    最小优先级                                                      
               启动之前设置优先级    t1.setPriority(10)
        线程等待:join()
                t1.join()    等待此线程执行完毕,下一线程开始执行     
        创建线程的三种方式:
                1>自定义一个类,继承Thread类,重写run方法,创建当前类对象,启动线程
                2>自定义一个类,实现runnable接口,重写run方法,创建线程thread类对象,将当前类对象作为参数传递,启动线程
                3>自定义一个类.实现Callable接口.实现里面call方法,完成异步任务操作,创建线程池,定义线程池数,创建当前类对象,作为参数传递异步任务submit中
         静态代理:
                核心思想:真实角色专注自己的事情,在开发中就是针对自己的业务
                               代理角色帮助真实角色完成一件事情
                               真实角色和代理角色要实现同一个接口
         解决线程安全:
                校验多线程是否安全的标准:   1>是否是多线程环境  2>是否有共享数据  3>是否有多条语句对共享数据的操作
                解决方案: 将多条语句对共享数据的操作使用同步代码块包起来,可以解决线程安全问题
                               synchronized(锁对象){多条语句对共享数据的操作}   
                                                   锁对象可以是任意java类型,但是多个线程必须使用同一个锁对象,否则锁不住
        什么是同步方法(非静态)?
                   如果一个方法中第一句话是一个同步的代码块,可以将synchronized关键字定义在方法声明上
                   权限修饰符  synchronized 返回值类型 方法名 (参数列表){ 多条语句对共享数据的操作}
                   锁对象:this  代表类对象的地址值引用   如果是静态的同步方法,它的锁和类有关,锁对象就是当前类名.class(字节码文件对象)
         使用synchronized解决线程安全问题,安全问题解决了,效率低,可能造成死锁现象
         死锁:两个线程出现了一种互相等待的情况,A等B释放锁,B等A释放锁,造成死锁现象,
                 解决死锁问题,线程之间的通信必须使用同一个资源,生产者和消费者模式思想   
        
        Java中的等待唤醒机制?
                     等待唤醒机制,使用"信号灯法"
                     解决线程安全前提下,造成死锁,多个线程使用同一个资源对象就是使用生产者消费者模式
                            使用生产者不断的产生数据,消费者不断 的使用数据(展示数据)
                            当生产者等待,先产生数据之后.通知消费者使用数据,消费者线程等待,先去使用数据,
                            当前没有数据了,需要通知生产者产生数据
                            在synchronized同步代码块/同步方法,需要使用锁调用wait()和notify(),调用wait会立即释放锁,完成唤醒操作
                            wait和noyify都和锁有关系,锁对象可以是任意java类型,Object代表所有类的父类,任意java对象可以使用Object,所以这两个也就定义在Object类中
        wait()和sleep()的区别?
                    来源不同,wait来自于Object,被锁对象调用   sleep来自于Tread类,线程睡眠,线程对象调用
                    wait方法调用,会立即释放锁,才能通过notify唤醒对方线程,达到同步安全
                    sleep只是线程类的普通方法,睡眠中线程处于阻塞状态,当睡眠时间到,线程继续执行
                    共同点就是都会抛出异常,中断异常InterruptedException          
       Lock锁:
               Lock接口    Lock提供比使用synchronized 方法和语句可以获得广泛的锁定操作     
               jdk提供锁Lock  priva Lock lock = new ReentrantLock();可重入的互斥锁   
               获取锁和释放锁   finally代码,释放资源去使用的,一定会执行,除非一种特例,在执行finally之前,jvm退出.excit(0);
线程池
创建一些固定的可以重复使用的线程数,在线程池中循环利用,当某些线程使用完毕,不会被释放掉,
         而是归还连接池中,等待下一次再去利用
         自定义类,实现Callable接口,重写call方法
         创建可重复的线程池:   ExecutorService es = Executor.newFixedThreadPool(2);
         执行异步任务:   es.submit(new Mycallable());      
         关闭线程池:    es.shutdown();
         有具体计算值的类型:
         Future<Integer> f1  = es.submit(new Mycallable(100));               
         Integer num = f1.get();
         sout(num);
         es.shutdown;
          <T> Future<T> submit(Callable<T> task); 提交异步任务,返回值就是异步任务计算的结果
          Future返回值:异步计算的结果:如果现在只是看多个线程是否能够并发的去强转CPU的执行权,并没有返回结果,这个返回值可以不用返回.
          获取具体的计算结果   Integer类型  num  =   f1.get();  输出num.   

        线程池7大参数:
                                1>核心线程数量
                                2>最大核心线程数
                                3>阻塞队列
                                4>生存时间
                                5>时间计量单位
                                6>拒绝策略
                                7>创建线程工厂
定时器
可以执行一次或者重复执行某个任务
          Timer  t = new Timer();   创建定时器
          t.cancel();   取消定时器
          自定义子类继承抽象类TimerTask
          t.schedule(new MyTask(),3000);    3000毫秒后执行这个定时线程任务
          t.schedule(new MyTask(),3000,2000);    3000毫秒后执行这个定时线程任务,经过固定时间2000毫秒重复执行任务.
File
用来描述路径形式
         File file = new File("路径地址精确到文件.后缀名");
          判断:
                  public boolean isFile():是否是文件       使用居多
                  public boolean isDirectory():是否是文件夹  使用居多
                  public boolean isAbsolute():是否为绝对路径
                  public boolean exists():判断文件或者目录是否存在   
          创建:                   
                  public boolean mkdir():创建文件夹,如果存在了,则返回false;否则true
                  public boolean mkdirs():创建多级目录,当父目录不存在的时候创建        
           删除:
                  boolean  delete();   目录必须为空      
           高级功能:  (加强for循环遍历文件名)
                          listFiles(); 获取指定抽象路径下的所有File数组    推荐只用File的功能进行判断
                          list():  抽象路径名表示的目录中的文件和目录       
           直接匿名对象过滤器  
                          File file = new File(new FileFileter(){ ......} );               
                          File file = new File(new FilenameFileter(){ ......} );
方法递归
1.需要有方法
         2.有一定的规律
         3.有方法结束的条件(出口条件),否则死递归
         核心就是方法调方法,并不是方法嵌套方法,构造方法没有递归   
         在方法结束return返回的时候调用方法本身来加入规律实现递归

IO流

InputStream   /    OutputStream
       分类:
              1.按照流的方向划分:
                            输入流      读
                            输出流      写                                                     
              2.按流的类型划分,同时按方向划分:
                           字节流
                                     字节输入流   不能new  具体子类   FileInputStream
                                     字节输出流    不能new  具体子类   FileOutputSream
                                     字节缓冲流(字节高效流)
                                           字节缓冲输入流   BufferedInputStream
                                           字节缓冲输出流   BufferedOutputStream
                           字符流
                                     字符输入流
                                             字符缓冲输入流
                                      字符输出流
                                              字符缓冲输出流
          创建字节输入流对象
                   FileInputStream  fis = new  FileInputStream("fis.txt");  
                   fis.read();   读文件  一次读一个字节,返回字节数 
                   fis.read(byte[] b);   读文件  一次读一个字节数组    
                               byte[ ] b = new byte[1024]     字节长度1024或者1024的整数倍          
          创建字节输出流对象
                   FileOutputStream  fos = new  FileOutputStream("fos.txt");
                   fos.write();   写入数据
                   fos.close();   释放资源  
                   创建字节输出流,实现文件的末尾追加,不将之前的覆盖,第二个参数必须为true.
                   windows  换行"\r\n"   Linux  换行"\r"  
          创建字节缓冲输入流(默认缓冲大小,长度8192)
                    BufferedInputStream  bis = new  BufferedInputStream(new FileInputStream"fis.txt");          
           创建字节缓冲输出流
                    BufferedOutputStream  bos = new  BufferedOutputStream(new FileOutputStream"fos.txt"); 
                             bos.flush();     强制刷新缓冲字节
                             释放资源:
                                            bos.close()
                                            bis.close()   先创建后释放
           字符流:
                      字符流是在字节流后出现的,如果是对文本进行操作,优先使用字符流
                      InputStreamReader/OutputStreamWriter:字符转换流弊端:代码格式复杂,不能直接操作文件!所以需要FileOutputStream/new   FileIntputStream
                      Writer:具体子类
                               创建字符缓冲输出流
                               OutputStreamWriter osw = new OutputStreamWriter(new   FileOutputStream"osw.txt")
                               osw.write(....);   写内容,可以写一个字符数组/字符数组的一部分/字符串
                      Reader:具体子类
                                创建字符缓冲输入流
                               InputStreamReader isr = new InputStreamReader(new   FileIntputStream"isr.txt")         
                               isr.read();   读内容,可以读一个字符,也可以读一个字符数组,读字符数组要将数组对象传入
                      InputStreamReader/OutputStreamWriter:字符转换流弊端:代码格式复杂,不能直接操作文件!
                                 所以需要FileOutputStream/new   FileIntputStream,里面包装了一层字节流操作,书写繁琐,
                                 所以又提供了子类FileReader/FileWriter   字符转换流的便捷类,跟idea平台默认字符集一致
                                 FileReader();  FileWriter();   字符流针对文件(使用高级记事本打开可以看懂),使用字符流操作,看不懂就用字节流
                                 创建 FileReader操作源文件
                                          FileReader fr = new  FileReader("fr.java");
                                  创建 FileWriter写数据
                                          FileWriter fr = new  FileWriter("d://.....路径");
                                  flush  刷新   close关闭     
           字符缓冲流:
                            创建字符缓冲输入流对象
                                    BufferedReader br = new BufferedReader(new FileReader("bw.txt")) ;
                                    BufferedReader的特有功能,    一次读取一行   br.readLine();
                                    
                           创建字符缓冲输出流对象  
                                    BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt")) ;
                                    bw.write();  写内容   
            字符流针对文本文件    
                    字符流读写复制
                   1)字符转换流InputStreamReader/OutputStreamWriter 一次读取一个字符/一次读取一个字符数组
                   2)使用字符转换流的便捷类FileReader/FileWriter 可以直击操作文件 一次读取一个字符/一次读取一个字符数组
                   3)使用字符缓冲流BufferedReader/BufferedWriter: 一次读取一个字符/一次读取一个字符数组
                   4)使用字符缓冲流BufferedReader/BufferedWriter :一次读取一行特有方式(推荐)

Properties(很重要)

Properties类  表示一组持久的属性   它可以保存到流中或者流中加载(重要)
                                   属性列表中的每个键及其对应的值都是一个字符串
                                   继承Hashtable     实现Map接口,存取都可以使用Map的方式
                  创建空的属性列表:
                                Properties pro = new Properties();
                                使用map集合的方式添加数据:
                                                                                pro.put(xxx);
                                遍历也同Map
                                                      keySet();      value=pro.get(key)     
                                                            
                 Properties属性列表有自己的遍历方式,底层基于map实现的
                              添加元素: pro.setProerty(键,值);
                              遍历:    Set<String> keySet = prop.stringPropertyNames();  然后加强for循环,使用键获取值pro.getProperty   最后sout(key  +   value)
                 如何读取src下面的 Properties配置文件      xxx.properties
                         1.获取当前类的字节码文件对象     class 正在运行的java类对象
                         Class  c = Test1.class;
                         2.class类     获取类的加载器   解析这个里面的所有成员(变量,方法   校验)
                         ClassLoader  cl = c.getClassLoder();
                         3.获取资源文件所在输入流对象   将资源文件的内容读取到字节输入流中
                         InputStream   is  = cl.getResourceAsStream("xxxx.Properties");
                         ****也可以一步走    InputStream   is   =    Test1.class.getClassLoder.getResourceAsStream("xxxx.Properties");
                         4.将输入流的对象内容加载属性列表中
                         pro.load(is);
                         通过键获取值:   String value = pro.getPropety("键")
                         输出值   sout(value);