1.String

1.新建对象

  1. 常量池(方法区)

    1
    String str="x";
  2. 新创建

    1
    Stirng str=new String("x");
  3. 区别

    常量池创建是在现有堆中查找是否有相同的内容,如果有指向同一数据;新创建中则忽略

    1. 先在常量池中创建再在新堆中创建,指向的内容不相等;先在新堆中创建,再在常量池中查找(此时的常量池就是刚创建的新堆)指向的内容相同;

      1
      2
      3
      String str1="x";
      String str2=new String("x");
      syso(str1==str2);//输出flase;
      1
      2
      3
      String str1=new String("x");
      String str2="x";
      syso(str1==str2);//输出true;
    2. 常量池中创建是在一个堆中,而新堆创建是在两个堆中

      1
      2
      3
      String str1="x";
      String str2="x";
      syso(str1==str2);//输出true;
      1
      2
      3
      String str1=new String("x");
      String str2=new String("x");
      syso(str1==str2);//输出flase

2.相关方法

  1. 检索str的位置

    没有检索到返回-1;

    1. 检索第一次出现str的位置:

      1
      int x = indexOf(str);
    2. 检索从n开始出现str的位置:

      1
      int x = indexOf(str,n);
    3. 检索最后一次出现str的位置;

      1
      int x = LastIndexOf(str);
  2. 获取指定位置字符串

    1. 获取从n1到n2的字符串

      1
      String str = str.substring(n1,n2);
    2. 获取从n开始到结尾的字符串

      1
      String str = str.substring(n);
    3. 获取位置n上的字符串

      1
      String str = str.charAt();
  3. 去除字符串前后的空字符串

    1
    String str = str.trim();
  4. 查询是否存在

    1. 以str2开头的字符串

      1
      boolean b = str.startsWith(str2);
    2. 以str2结尾的字符串

      1
      boolean b = str.endsWidth(str2);
  5. 正则表达式方法

    1. 是否存在正则表达式相配数据

      1
      boolean b = str.matches(“正则表达式”);//true:相同
    2. 将一个字符串拆分成字符串数组

      1
      String[] b = str.split(正则表达式);
    3. 将字符串的一部分用于替换

      1
      String b = str.replaceAll(正则表达式,被替换);

3.StringBuffer/Builder

  1. String是不可变的(被final修饰);

    1
    2
    String str="1";
    str=str+"2";

    流程:JVM创建第一个str对象并赋值”1”,创建第二个str并赋值”12”,GC垃圾回收机制处理掉第一个str

  2. StirngBuffer是可变的

  3. StringBuffer是线程安全的,StringBuilder是线程不安全的;StringBuilder是性能最好的;

2.集合

1.基础知识

  1. 数组和集合的区别

    1. 数组长度不可变,集合的长度可变;
    2. 数组无法保存具有映射关系的数据;
    3. 数组可以保存基本数据和对象,集合只能保存对象(对象的引用变量);
  2. 所属包:

    java.util(工具类,java5以后再java.util.concurrent包下提供线程安全集合类)

  3. 包含类:

    1. Collection:接口类,集合框架的根接口
    2. Map:接口类,集合框架的根接口

2.Collection集合

1.基础知识

1.Collection
  1. 基础知识:

    1. collectoion是顶级父类接口;Set/List是子接口
    2. Collection接口派生的集合默认长度为0
  2. 关系图:

2.List和Set的区别
  • List集合是序列(有序)的,允许元素重复;
    • java.util.ArrayList:
      1. 内部由数组实现,查询效率好;
      2. 修改必须新建重新赋值;
    • java.util.LinkedList:
      1. 内部由链表实现,增删效率好,尤其是首尾增删;
      2. 查询慢必须一个一个查询,修改快,只需要插入即可
  • Set集合是散列(无序)的,不允许元素重复(若重复则只显示一个):
    • 相同元素的标准:2个对象的equals()对比结果为true且hashCode()返回值相同
    • 如果使用的实现类是TreeSet,还要求集合中的元素实现Comparable接口。
3.Collection共有方法
  1. 新建对象:

    set/array亦可

    1
    Collection<Integer> collection = new Collection<Integer>();
  2. 添加:

    1. 添加元素:

      1
      collection.add(1);
    2. 将集合2的数据复制到集合1中:

      如果collection是list集合重复的数据只显示一份,set集合可以重复

      1
      collection.addAll(collection2);
  3. 删除:

    1. 删除元素:

      1
      collection.remove(1);
    2. 删除两个集合中相同的元素

      1
      collection.removeAll(collection2);
  4. 集合的大小

    1
    int size = collection.size();
  5. 空集

    1. 清空为空集

      1
      collection.clear();
    2. 检测是否为空集

      1
      boolean is = collection.isEmpty();
  6. 更改元素:将位置1的数值更改为2;仅适用于List

    1
    collection.set(1,2);
  7. 包含

    1. 判断集合中是否有1;

      1
      boolean contain = collection.contain(1):
    2. 判断C1中是否包含C2中的所有元素

      1
      boolean contains = collection.containAll(c2);

2.遍历集合

1.Iterator
1.Iterator
  1. 属性:

    1. 位于顶级父类Collection中的方法;

    2. 遍历数组时里面不能使用集合的方法(多数情况下会报错)

    3. 执行读写删读写删操作;

    4. 步骤

      1. 创建集合

        1
        Collection c = new ArrayList();
      2. 返回一个迭代器,返回Iterator类型的对象

        1
        Iterator it = c.iterator();
      3. 遍历

        遍历时别修改集合的值会报错

        1
        2
        3
        4
        while(it.hasNext()){			//判断是否还有下一个元素可以遍历
        String o =(String)it.next();//将接收到的内容强制转换为String类型
        it.remove(); //删除调用的集合 (此处不能使用集合的方法)
        }
2.匿名内部类
  1. 原理

    Iterable接口新增一个forEach()默认方法,Iterable接口是Collection接口的父接口

  1. 遍历

    1
    it.forEachRamaining(obj -> System.out.println("迭代集合元素:"+obj));
2.增强for
1.增强for

​ 新循环是编译器认可的,编译器编译或将新循环遍历数组为普通for;

  1. 数组:

    1
    2
    3
    4
    5
    6
    7
    8
    for(int i = 0; i<arr.length;i++) {
    String str = arr[i];
    System.out.println(str);
    }
    for(String str : arr) {
    System.out.println(str);
    }
    Arrys.toString(arr);
  2. 集合:

    新循环遍历集合会被编译器改为迭代器遍历(不需要返回一个迭代器了)

    1
    2
    3
    4
    5
    6
    7
    8
    for(Object o : c) {
    String str = (String)o;
    System.out.println(str);
    }
    Collection<String> c = new ArrayList<String>();//指定类型
    for(String str : c) {
    System.out.println(str);
    }
2.匿名内部类

表达式

1
books.forEach(obj -> System.out.println("迭代集合元素:"+obj));

3.Set

1.HashSet

当向HashSet集合中添加可变对象时,如果修改集合中对象,有可能导致对象与集合中的其他对象相同,从而导致HashSet无法准确访问该对象

  1. 添加规则

    1. 判定元素是否重复标准

      1. 比较两个元素的hashCode()方法返回的hashCode值,如果不相等则为合格;
      2. 两个元素进行equals()比较是否为同一对象,如果结果为flase则为合格;
      3. 以上两个只有有一个合格就可以添加成功,;
    2. 单个合格的缺点

      1. eualas合格,hashcode不合格:就会导致两个元素被分配到不同的hash值地址上,但是元素是相同的,与set规则不相符(元素不可以重复);
      2. hashcode合格,equals不合格:就会导致两个元素被分配到相同的hash值地址上,用链表的形式保存,因为查找元素是靠hash值,这样会导致查询速度变慢;
    3. 重写hashCode和equals规则

      如果重写euals方法时就要重写hashCode;hashCode和equals都为合格或都为不合格

  2. 重写HashSet

    1. HashSet计算公式:

      通常只使用引用类型

    2. 计算Haash值

      1. 方法1:

        1
        2
        3
        public int code(){
        return f1.hashCode()*17+f2.hashCode()*31+...;
        }
      2. 方法2:

        1
        2
        3
        4
        5
        6
        7
        public int code(){
        int result = 17;
        result = result * 31 + ((Book == null) ? 0 : Book.hashCode());
        result = result * 31 + ((Name == null) ? 0 : Name.hashCode());
        ...
        return result;
        }
      3. 方法3:

        eclipse自动生成

2.linkedHashSet
  1. HashSet的子类,拥有HashSet的功能;
  2. 存储:
    1. 排序方式:按照集合元素的添加顺序;
    2. 存储位置:按照hash值存储
  3. 通过链表维护集合元素的顺序,是一个有序的set,不可重复
  4. add时性能略低与HashSet,遍历时性能略高于HashSet
3.TreeSet
  1. 基础知识:

    1. TreeSet是SortSet接口的实现类;SortSet是Set的子接口;
    2. 存储:
      1. 排序方式:按照集合内元素的大小排序;
      2. 存储位置:按照红黑树数据结构;
  2. 相关方法

    1. 返回第一个元素

      1
      treeSet.firset();
    2. 返回最后一个元素

      1
      treeSet.last();
    3. 元素的前一个元素

      1
      treeSet.last();
    4. 元素的后一个元素

      1
      treeSet.last();
    5. 返回t1和t2之间元素(以集合的形式)

      1
      treeSet set = subSet(t1,t2);
    6. 返回小于t的所有元素(以集合的形式)

      1
      treeSet set = headSet(t);
    7. 返回大于t的所有元素(以集合的形式)

      1
      treeSet set = tailSet(t);
    8. 排序方式:

      1. 基础知识:

        1. 要添加的元素最好是同一类型,否则会报错;
        2. 要添加的元素的实体类一定要有排序规则;
        3. 如果修改添加完的数据会导致大小顺序发生改变不会刷新,并且重复和修改的数据不能被删除
      2. 自然排序:

        1. 排序原理:

          调用元素的compareTo(Object obj)方法比较元素之间的大小,然后将元素升序排序;

        2. 实现方法:

          实体类实现Comparable接口,重写compareTo(Object obj)方法,定义排序规则;

        3. 排序规则:

          A1.compareTo(A2)返回值>0代表A1>A2;

          A1.compareTo(A2)返回值<0代表A1<A2;

          A1.compareTo(A2)返回值=0代表A1=A2;

        4. 排序公式:

          1
          2
          3
          4
          5
          6
          7
          8
          class student() implements Comparable{
          private String name;
          private Integer id;
          public int compareTo(Studnet student){
          return id-student.id;
          return id-student.id>0?1:id-student.id<0?-1:0;
          }
          }
      3. 定制排序:

        1. 排序原理:

          ThreSet的自然排序是根据集合元素的大小,TreeSet将他们以升序排列;

        2. 在新建TreeSet对象时,传入一个实现Comparator接口并重写compare(T1,T2)方法的对象,在compare中重新定义排序规则

        3. 排序公式

          1
          2
          3
          new TreeSet((School s1,School s2)->{
          return s1.getId()-s2.getId();
          });
4.EnumSet

枚举类

4.List

1.基础知识
  1. 属性:

    有序列表HashSet不继承List;

  2. 实现类:

    1. 一般使用ArrayList
  3. 方法(不包括collection)

    List list = new ArrayList();//括号内可以传入一整个集合

    1. 将位置2添加新元素12

      1
      list.add(2,”2”);
    2. 将位置2删除

      1
      list.remove(2);
    3. 将位置2更新为3

      1
      list.set(2,”3”);
    4. 获取位置2

      1
      list.get(2);
    5. 生成list的[3,8)的子集subList

      1
      List.subList=list.subList(3,8);
    6. 将生成的子集删除(子集修改父集也会被删除)

      1
      list.subList(3,8)clear();
    2.转换
  4. 集合转换数组

    toArray是Collection的方法,他的子类也可以使用;

    1
    2
    Collection c = new ArrayList();
    String[] array = c.toArray(new String[c.size()]);

    c.size的长度没有达到数组该有的长度会补齐

  5. 数组转换集合

    Arrays提供了一个静态方法asList,将数组转换为List集合

    1
    2
    3
    String[] arr =  {"one","two","three","four"};
    List list = Arrays.asList(arr);
    Arrays.toString(arr);
4.栈结构
  1. 队列:先进先出;//后进前出

    1. 所属类:

      java.util.queue

    2. 父类:

      Collection

    3. 实现类:

      LinkedList

    4. 方法

      1
      2
      3
      4
      5
      Queue<String>  queue = new LinkedList<String>();
      tring str = queue.poll();//将第一个输出(输出后在集合中消失)
      依次输出:用i--;因为只有定义为初始值才不会改变;
      str = queue.peek();//将第一个输出
      queue.offer("a");//在后面添加一个数
  2. 双端队列:两端都可以输入输出;

    1. 所属类:

      java.util.Deque

    2. 父类:

      queue

    3. 实现类:

      LinkedList

    4. 方法:

      1
      2
      3
      4
      deque.offerFirst();
      deque.offerLast();
      deque.pollFirst();
      deque.polLast();
  3. 栈结构:再同 一端进入输出可用于前进后退功能

    1
    2
    queue.push();
    queue.poll();

3.Map集合

  1. 新建map

    1
    Map map<String,String> = new Map<String,String>();
  2. 返回所有key

    1
    Set<String> keys = map.keySet();
  3. 返回所有value

    1
    Set<String> values = map.keyValue();

4.Collections

所属类:

java.util.Collections (Collection的集合工具类);

1.封装线程安全集合

  1. Collection

    1
    2
    Conllection collection = new ArrayList();
    collection = Collections.synchronizedList(list);
  2. List

    1
    2
    List list = new ArrayList();
    list = Collections.synchronizedList(list);
  3. Set

    1
    2
    Set set = new HashSet(list);
    set = Collections.synchronizedSet(set);
  4. SortedMap/Tree

  5. SortedSet/Tree

2.List集合排序

  1. 自然排序

    1. 升序操作

      1
      Collections.sort(list);
    2. 自定义排序

      Comparator:自然排序重写

      1
      Collections.sort(list,Comparator);
  2. 乱序

    1
    collections.shuffle(list);
  3. 翻转排序

    1
    collecions.reverse(list);

3.创建不可变集合

3.线程

1.注意事项

main方法也是一个线程

2.创建线程

​ 建议使用Runnable或Callable

  1. 由于java里一个类只能继承一个父类,所以Thread只能继承一个父类,而runnable和callable可以继承多个父类
  2. runable和callable可以实现代码的分离,面向对象
  3. runable和callable代码复杂,获取线程对象要用Thread.currentThread()方法,而thread可以直接对象点;

1.继承Thread

  1. 新建线程:新建类继承Throw,重写run方法

    1
    2
    3
    4
    5
    public class Test() extends Throw(){
    public void run(){
    线程需要执行的内容;
    }
    }
  2. 创建线程:

    1
    Test test = new Test();
  3. 启动线程:创建一个新的栈,而不是创建栈帧

    1
    test.start();

2.实现Runnable

  1. 新建线程:新建线程类,实现Runnable接口,重写run方法

    1
    2
    3
    4
    5
    public class Test implements Runnable{
    public void run(){
    线程内容;
    }
    }
  2. 创建线程对象

    1
    Test test = new Test();
  3. 新建线程

    1
    Thread thread = new Thread(thread[,"线程名"]);
  4. 执行线程

    1
    thread.start();

3.使用Callable和Future

  1. 新建线程:新建范方法线程类,实现Callable类,重写call方法
    可以抛出异常而不需要必须在县城里处理

    1
    2
    3
    4
    5
    public class Test implements Callable<call方法返回值>{
    public Integer call() throws Exception{
    线程内容;
    }
    }
  2. 新建线程对象

    1
    2
    Test test = new Test();
    FutureTask<Integer> result = new FutureTask<>(test);
  3. 执行线程

    1
    Thread thread = new Thread(result);
  4. 执行线程

    1
    therad.start();
  5. 返回值:get()会阻塞到结束时执行

    1
    2
    3
    try{
    Integer sum = result.get();
    }catch(){}

4.其他方法创建

1.匿名内部类
  1. Thread

    1
    2
    3
    4
    5
    Thread thread = new Thread(){
    public void run(){
    }
    }
    thread.start();
  2. Runnable

    1
    2
    3
    4
    5
    Thread thread = new Runnable(){
    public void run(){
    }
    }
    new Thread(thread.start());
2.Lambda表达式

当新建的线程类中只有一个方法时就可以使用Lambda表达式

5.Threa对象

  1. 获取线程对象(静态)

    1. run方法内

      只适用于实现Runnable或Callable的接口的run方法内执行

      不能使用this,this指的是线程类这一个对象,而静态方法获取的是不同的三个对象

      1
      Thread thread = Thread.currentThread();
    2. 线程外获取对象

      1
      2
      Test test = new Test();
      Thread thread = new Thread(test);
  2. 获取线程名

    1
    String name = thread.getName();
  3. 获取线程id

    1
    Int id = thread.getId()
  4. 获取线程优先级[见下文]

    1
    thread.getPriority();
  5. 检查是否处于活动状态[见下文]

    线程处于:就绪/运行/阻塞返回true,处于新建/结束返回flase;

    1
    thread.isAlive();
  6. 检查是否为守护线程[见下文]

    1
    thread.isDaemon();
  7. 检查是否被中断

    1
    thread.isInterrupted();

3.生命周期

  1. 图表

    状态 线程
    新建 使用new关键字创建线程后
    就绪 线程对象调用start()方法后
    运行 获得cpu资源,执行run方法体后
    死亡 run()结束/错误/执行stop()
  2. 图示

    线程从阻塞状态只能进入就绪状态

  3. 注意事项

    1. 主线程和子线程:

      主线程和子线程有相同的地位,子线程不收主线程的影响,主线程结束后子线程可以继续执行;

    2. start()

      对新线程两次调用start()或者对死亡的线程调用start()都会抛出异常illegalThreadStateException

      调用run()方法以后不能再次调用start()方法会抛出异常

4.控制线程

  1. 新建线程:

    Thread/Runnable/Callable

    1
    2
    Test test = new Test();
    Thread thread = new Thread(test);

1.join

因为阻塞后会处于就绪,因此.start()可以解除join

  1. 在therad2线程中调用thread.join()方法,therad2会被一直阻塞,直到therad执行完毕

    1
    thread.join();
  2. 在therad2线程中调用thread.join(n毫秒)方法,therad2会被一直阻塞n毫秒

    1
    thread.join(n);

2.后台线程(守护线程)

  • 注意事项:
    • 当前台线程全部执行完毕,守护线程也随之结束,jvm的gc就是守护线程,
    • 线程处于:就绪/运行/阻塞返回true,处于:新建/结束返回flase;
    • 前台线程创建的默认是前台线程,后台线程创建的线程默认是后台线程;
  1. 设置为后台线程

    必须在thread.start()之前执行,否则返回illegalThreadStateException

    1
    thread.setDaemon(true);
  2. 获取当前线程状态

    1
    boolean flag= thread.getDaemon();

3.sleep(线程休眠)

可能发生死锁,尽量少使用,run方法内执行

  1. 让thread线程休眠

    1
    Thread.sleep();
  2. 让thread休眠n毫秒(收系统精度影响)

    1
    Thread.sleep(n);

4.yield(线程让步)

移植性低,不建议使用,建议使用sleep

会将线程强制转换到就绪状态,而不是阻塞,在执行后会暂停并给大于等于自身优先级的线程(包括)执行机会,

1
Thread.yield();

5.设置优先级

每个线程默认的优先级都与创建它的父线程优先级相同;

  1. 优先级级别

    1. 范围从1-10,但是由于要受操作系统的影响,所以应该尽量使用常量优先级

    2. 常量优先级

      常量 级别
      Thread.MAX_PRIORITY 10
      Thread.MIN_PRIORITY 1
      Thread.NORM_PRIORITY 5(main)
  2. 获取优先级

    1
    int x = thread.getPriority();
  3. 设置优先级

    1
    thread.setPriority(优先级);

5.线程同步

1.并发产生的原因

1
2
3
4
5
int total2=2000
if(total>total2){ //1
syso("取钱成功:");
total2=total2-1500; //2
}

如果线程1在经过1时正好堵塞,线程2在此期间执行完毕,这时线程1再执行完毕则出现错误;也就是说有同时执行1的可能

2.同步代码块

参数是同步监视器:当一个线程使用obj时阻止其他线程使用,直到代码块执行完毕

  • 同步监视器:obj,需要竞争的对象资源
  • 同步代码块:需要执行的操作
1
2
3
synchronized(obj){			//加锁
同步代码块 //修改
} //释放锁

3.同步方法

在自定义类中加同步方法:被synchronized修饰的方法,默认同步监视器是this就是当前对象;

1
2
3
public synchronized void XXX(){
同步代码块
}

4.同步锁

在实现方法中书写同步锁:java8新功能,ReentrantLook可以被多次加锁

  1. 步骤

    1. 新建ReentrantLook(可重入锁)

      1
      private final Look look = new ReentranLook();
    2. 代码开头加锁

      1
      look.look();
    3. finally中解锁

      1
      look.ulook();
  2. 案例

    1
    2
    3
    4
    5
    6
    private final ReentrantLock lock = new ReentrantLook(); 
    public void x(){
    look.look();
    try{代码}
    finally{look.unlook()};
    }

5.死锁

在系统中出现多个同步监视器的情况下容易死锁;

6.同步监视器何时释放和锁定

  1. 释放同步监视器的锁定
    1. 同步方法或代码块执行结束
    2. 遇到break/return提前结束同步方法或代码块
    3. 出现未处理的error或Exption导致同步放那个发或代码块结束
    4. 执行了同步监视器对象的wait()方法,使当前线程暂停会释放监视器
  2. 不释放同步监视器的锁定(容易死锁)
    1. Thread.sleep()/Thread.yield()
    2. suspend()将线程挂起

6.线程通信

1.传统通信

  1. 相关方法:

    Object的三种方法,仅适用于同步块和同步方法

    1. 当前线程等待,知道调用notify()或notifyAll();

      1
      wait();
    2. 唤醒在此同步监视器上等待的单个线程

      1
      notify();
    3. 唤醒在此同步监视器上等待的所有线程

      1
      notifyAll();
  2. 案例:

    当程序进入draw2()存钱方法后,如果flag为true,表示账户中有人正在取钱,程序调用wait()方法阻塞存钱方法;反之如果flag为flase表示账户中没有人正在存钱此时执行存钱操作,最后将flag设置为true,并唤醒存钱期间被阻塞的取钱操作,被唤醒的取钱线程会执行取钱操作最后将flag设置为false,并唤醒取钱期间被阻塞的存钱操作;
    注意事项:在类中设置flag默认为flase,所以直接执行取钱操作就会有问题;

    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 A{
    private String ANo;//账户编号
    private double price;//账户余额
    private boolean flag = false;//true:有人正在取钱|false:有人正在存钱
    get/set/toString(price只写get处于安全考虑)

    public synchronized void draw(double price2){
    try{
    if(!=flag){
    wait();
    }else{
    price = price - price2;
    flag = false;
    notifyAll();//唤醒其他线程;
    }
    }
    }

    public synchronized void draw2(double price2){
    try{
    if(flag){
    wait();
    }else{
    price = price + price2;
    flag = true;
    notifyAll();//唤醒其他线程;
    }
    }
    }
    }

2.Condition通信

  1. 步骤

    仅适用于同步锁

    1. 新建look对象

      1
      private final Look look = new ReentrantLook();
    2. 获得Condition对象

      1
      private final Condition conditon = Conlook.newCCondition();
    3. await();

    4. signal();

    5. signalAll();

  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
    public class A{
    private String ANo;//账户编号
    private double price;//账户余额
    private boolean flag = false;//true:有人正在取钱|false:有人正在存钱
    get/set/toString(price只写get处于安全考虑)
    public void draw(double price2){
    look.look();
    try{
    if(!=flag){
    wait();
    }else{
    price = price - price2;
    flag = false;
    notifyAll();//唤醒其他线程;
    }
    }catch(){
    }finally{
    look.ulook;
    }
    }
    public void draw2(double price2){
    try{
    if(flag){
    wait();
    }else{
    price = price + price2;
    flag = true;
    notifyAll();//唤醒其他线程;
    }
    }
    }
    }

3.阻塞队列[待学]

7.线程组和未处理的异常

8.线程池

1.相关线程池

线程池 作用 注意事项
newFixedThreadPool() 固定数量线程池
newCachedThreadPool() 缓存线程池
newScheduledThreadPool() 周期性线程池
newSingleThreadExecutor() 单线程线程池

2.创建线程池

  1. 创建线程池

    1
    ExcutorService pool = Executors.线程池();
  2. 创建线程池

    1
     
  3. 向线程池中提交线程(可提交多个)

    1
    pool.submit(target);
  4. 关闭线程池

    1
    pool.shutdown();

9.线程相关类

1.ThreadLocal

2.包装线程

3.线程安全

  1. 集合:详情请见Collections中
  2. Random—–ThreadLocalRandom

4.IO操作

1.File类

1.相关方法

  1. 新建对象,而不是文件(file为地址);

    1. 自定义地址创建

      1
      File file = new File("/demo");
    2. 在指定目录下创建[只在大量创建子目录时使用]

      1
      File file = new File(mkdir,"demo");
  2. 显示File信息

    1. 地址

      1
      2
      file;//方法1:直接输出file对象,不是String类型
      String path = file.getPath();//方法2
    2. 文件/目录名

      1
      String name = file.getName();
    3. 绝对地址=绝对名字

      1
      2
      File AbsoluteFile = file.getAbsoluteFile();//方法1
      String absolutePath = file.getAbsolutePath();//方法2:absolluteFile().tostring();
  3. 检测

    1. 是否是目录或文件

      1
      boolean exists = file.exists();
    2. 是否是目录

      1
      boolean directory = file.isDirectory();
    3. 是否是目录

      1
      boolean file = file.isFile();
  4. 创建/删除

    1. 创建目录

      1
      mkdir.mkdir();//(父级目录必须存在,例如"A//b//,则A必须存在")
  5. 创建多级目录

    1
    mkdirs.mkdirs();//(腹肌目录不存在会一起创建)
    1. 创建文件(需要处理IOException)

      文件可能被占用

      1
      file.createNewMkdir();
    2. 删除文件/目录

      不能删除非空目录,见案例详述

      1
      file/mkdir.delete();
  6. 其他

    1. 文件/目录大小

      1
      long length = file/mkdie.length();
    2. 返回目录下的所有文件和目录地址

      1
      File[] list = mkdir.listFiles();
    3. 返回目录下的所有文件和目录名

      1
      String[] list = mkdir.list();
    4. 转换为nio的path对象

      1
      Path path = file.toPath();
  7. 临时目录

    前缀最少3位数,并且是生成以前缀为开头的随机文件名

    1. 新建临时文件夹

      1
      File.createTempFile("前缀","后缀");
    2. 在指定目录下创建临时文件夹

      1
      File.createTempFile("前缀","后缀","指定目录");
  8. 案例(删除非空目录)

    1. 方法1

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      public static void delete1(File file) {
      if (file.exists()) {
      if (file.isFile()) {
      file.delete();
      } else {
      File[] list = file.listFiles();
      for (File file2 : list) {
      file2.delete();
      }
      file.delete();
      syso("删除完毕");
      }
      }else {
      System.out.println("要删除的文件或目录不存在");
      }
      }
    2. 方法2(return)迭代方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      public static void delete2(File file) {
      if(!file.exists()) {
      return;
      }else if(file.isFile()) {
      file.delete();
      return;
      }else {
      File[] files = file.listFiles();
      for(File file2 :files) {
      delete2(file2);
      }
      file.delete();
      }
      System.out.println("删除完毕");
      }

2.FileNameFilter

​ 函数式接口

  1. 实现方法:

    1. 新建类实现FileNamefilte,重写accept(File dir,String name)方法 dir:父目录,name:字文件目录名称
    2. 1中类返回满足的要求
  2. 案例

    1
    2
    3
    4
    5
    6
    public boolean accept(File dir, String name) {
    boolean endsWith = name.endsWith(".f");
    //name只有new File才能使用File的方法
    //boolean directory = new File(name).isDirectory();
    return endsWith;
    }
  3. FileNameFilter与FileFilter的区别

    1. 传入参数不同,FileFilter也实现accept但是传入(File file)方法
    2. FileFilter不适用于file.list()方法

2.byte

  1. 字节换算

    1KB=1024B=1byte(字节)=8bit(比特)

    1B(字节)=8b(比特)

  2. UTF-8

    字符集 中文 英文
    UTF8 3个字节 1个字节
    GBK 2个字节 1个字节
  3. byte[]转换

    1. String转换为byte[]

      1
      byte[] bates = str.getBytes("字符集");
    2. byte[]转换为String

      1
      String str = new String(bates,"字符集");

3.RandomAccessFile

1.基础知识

  1. 所属类

    java.io.RandomAccessFile

  2. 作用:

    进行文件的byte单字节读写

  3. 原理:

  4. 指针读取:

    1. 每写入1byte(字节),指针移动1个位置.

    2. 同一个raf对象指针的位置不重置为0的,如果要读取,要先raf.seek(0);

    3. 不同的raf默认指针位置为0再次写操作会覆盖写入的部分;

    4. 由于第一次写入1个String类型占3个字节,第二次写入一个int类型占2个字节,还剩余一个字节就会抛出EOFException异常

      1
      2
      3
      4
      dyte[] dates = new dates[];
      String str = new String ("x","字符集");
      raf.seek();
      raf.writeInt(1);

2.相关方法

  1. 创建对象

    如何file为r,而选择rw访问模式则直接报错

    r:读:如果写操作会抛出io异常

    rw:读写:如果没有文件会尝试创建文件

    1
    RamdomAccessFile raf = new RamdomAccessFile(file,"rw");
  2. 写入

    1. char/ASCII写入

      1
      read.write();
    2. 写入数组大小数据并导入数组中

      1
      read.write(dates);
    3. 写入数组n1-n2位置数据并导入数组中

      1
      read.write(dates,n1,n2);
    4. int/double/其他类型

      当读取到末尾时会抛出EOFException

      1
      raf.writeInt();/raf.writeUTF();
    5. UTF

      虽然传入的是String类型内容,但是写入的是不同类型(“1”–int/“你好”–String)

      1
      raf.UTF("1");/raf.UTF("你好");
  3. 读取

    1. char/ASCII读取(文档不乱码)

      1
      raf.read();
    2. 读取数组大小数据并导入到数组中

      1
      raf.read(dates);
    3. int/UTF(不乱码)读取

      1
      raf.readInt();/raf.readUTF();
  4. 指针

    单位是byte(字节)

    1. 当前指针位置

      1
      raf.getFilePoint();
    2. 指定指针位置

      1
      raf.seek(0);
    3. 当前总指针数/文件大小

      1
      raf.length();
  5. 关闭流

    1
    raf.close();

3.案例

1.String写入或读写
  1. 写入

    1
    2
    3
    String str = "x";
    byte[] bytes = str.getBytes(str,"字符集");
    raf.write(bytes);
  2. 读取

    1
    2
    3
    4
    raf.seek(0);
    byte[] bytes = new byte[raf.length()];
    raf.read(bytes);
    String str = new String(bytes,"字符集");
2.ASCII和char写入或读写
  1. 写入

    1
    raf.write('a');/raf.write(49);
  2. 读取

    1
    2
    3
    4
    int code = -1;
    while((code=raf.read()) != -1){
    syso(code);
    }
  3. Other写入或读写(readInt/readUTF)

    1. 写入

      1
      raf.writeInt(123);/raf.UTF("123");
    2. 读取

      1
      2
      3
      while(raf.getFilePoint != raf.length()){
      raf.read();
      }
3.文件复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
RandomAccessFile raf1 = null;
RandomAccessFile raf2 = null;
try {
raf1 = new RandomAccessFile(file, "rw");
byte[] bytes = new byte[1024];
raf1.read(bytes);
raf2 = new RandomAccessFile("D:\\B.txt", "rw");
raf2.write(bytes);
System.out.println("复制成功");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
raf1.close();
raf2.close();
} catch (IOException e) {
e.printStackTrace();
}
}

5.Other

最后更新: 2019年11月06日 11:36

原始链接: https://airbash.cn/2019/11/01/JAVA/JavaAPI/

× 请我吃糖~
打赏二维码