Java基础知识点汇总

  • 一. Java基础语法
    • 1. 类型转换
    • 2. 方法
    • 3. 位运算
    • 4. 循环
    • 5. 装箱与拆箱
    • 6. 内存分析
  • 二. 面向对象
    • 1. 概念
    • 2. 对象的初始化与创建
    • 3. 创建对象的内存分析
    • 4. 封装
    • 5. 继承
    • 6. 多态
    • 7. Instanceof
    • 8. Static关键字、代码块
    • 9. 抽象类
    • 10. 接口
    • 11. 方法的重写和重载
  • 三. 异常处理
  • 四. 集合
    • 1. 集合的概念
    • 2. Collection体系
    • 3. Collection中常用方法
    • 4. Iterator迭代器
    • 5. Contains方法
    • 6. 集合转数组
    • 7. Remove方法
    • 8. List集合
    • 9. 泛型
    • 10. HashSet集合
    • 11. TreeSet集合
    • 12. Map接口常用方法
    • 13. Map的遍历
    • 14. HashMap
    • 15. HashTable集合
    • 16. Properties集合
    • 17. TreeSet集合元素排序
    • 18. 自平衡二叉树
    • 19. Collections工具类
  • 五. IO流
    • 1. 什么是IO
    • 2. IO流的分类
    • 3. IO流四大家族
    • 4. FileInputStream和FileOutputStream
    • 5. FileReader和FileWriter
    • 6. 文件拷贝
    • 7. BufferedReader和BufferedWriter
    • 8. PrintStream
  • 六. 注解
  • 七. 反射
    • 1. Class类
    • 2. Class类的实例
    • 3. Class类的创建方式
    • 4. 类加载器
    • 5. 获取类运行时完整结构
    • 6. 动态创建对象调用方法和属性
  • 八. 多线程
    • 1. 概念
    • 2. 创建线程的三种方式
    • 3. 静态代理
    • 4. Lambda表达式
    • 5. 停止线程
    • 6. 线程休眠
    • 7. 线程礼让
    • 8. 线程强制执行
    • 9. 线程状态
    • 10. 线程优先级
    • 11. 守护线程
    • 12. 线程同步机制
    • 13. 死锁
    • 14. Lock(锁)
    • 15. 线程池
    • 16. wait和notify
    • 17. 生产者消费者

一. Java基础语法

1. 类型转换

        // 强制类型转换
        float a = 20.34f;
        int b = (int)a;
        //自动类型转换
        int c = 10;
        float d = c;
        //操作较大的数时,注意溢出问题
        //JDK7新特性,数字之间可以用下划线分割
        int money = 10_0000_0000;
        int years = 20;
        long total = money * years;//默认两个参数都是int,计算的时候产生溢出
        System.out.println(total);//-1474836480

        long total_2 = money*((long)years);//先把一个数转化为long
        System.out.println(total_2);//20000000000

2. 方法

    public static void main(String[] args) {
        // 可变参数的传递
        Demo01 demo = new Demo01();
        demo.printMax(2,485,1,2,344,5);
    }

    public void printMax(int ...numbers){ //仅能为最后一个参数才能使用...}

3. 位运算

       //位运算
        /*
        * A = 0011 1100
        * B = 0000 1101
        * --------------
        * A & B = 0000 1100       对应位置都为1才为1
        * A | B = 0011 1101       对应位置有一个为1,结果为1
        * A ^ B = 0011 0001       对应位置相同为0,不同为1
        * ~ B = 1111 0010         对应位置取反
        *
        *
        * 2 * 8 =16,  2*2*2*2
        * << 左移  *2
        * >> 右移  /2
        *
        * 0000 0000   0
        * 0000 0001   1
        * 0000 0010   2
        * 0000 0011   3
        * 0000 0100   4
        * 0000 1000   8
        * 0001 0000   16
        *
        * */

4. 循环

        //增强for循环
        int[] numbers = {10,20,30,40};

        for (int x:numbers){
            System.out.println(x);
        }

5. 装箱与拆箱

6. 内存分析

二. 面向对象

1. 概念

面向对象的本质:以类的方式组织代码,以对象的方式封装数据。
三大特性:封装,继承,多态。

2. 对象的初始化与创建

使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中的构造器的调用。一旦定义了有参构造,无参构造就必须要显示定义。

3. 创建对象的内存分析

4. 封装

程序设计的要求:“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
封装(数据的隐藏):应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问。

5. 继承

所有的类都默认直接或者间接继承Object类。JAVA中类只有单继承,无多继承。私有的东西无法被类继承。

6. 多态

多态存在的条件:① 有继承关系。② 子类重写父类的方法。③ 父类引用指向子类对象。④ 多态是方法的多态,属性没有多态。⑤ 对象能够执行的方法,主要看左边的类型。当子类重写了父类的方法,所调用的皆是子类的方法。

7. Instanceof

Java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。

8. Static关键字、代码块

Static关键字和类一起加载,可以直接通过 (类名.静态方法) 调用方法。
代码块:执行顺序:静态代码块 > 构造方法 > 匿名代码块。静态代码块只执行一次,即使有多个同一个类的实例,仍只运行一次。

9. 抽象类

① 抽象方法,只有方法的名字,没有方法的实现。② 不能new抽象类,只能靠子类来实现。③ 抽象方法必须在抽象类中,抽象类中可以有普通方法。 ③ 抽象类的所有方法,都需要由它的子类来实现。 除非子类为抽象类,则由子子类实现。

10. 接口

① Interface 定义的关键字,接口都需要有实现类。② 接口中所有方法都是抽象的:public abstract,接口只可做方法的声明。 ③ 类实现接口需要重写接口中的所有方法。④ 利用接口可以实现多继承。

11. 方法的重写和重载

  • 方法的重写

    ① 需要有继承关系,子类重写父类的方法,与属性无关。
    ② 方法名相同,参数列表必须相同,方法体不同。
    ③ 修饰符范围可以扩大但不能缩小:public>protected>default>private。
    ④ 抛出的异常范围可以缩小但不能扩大。

    ⑤ 重写的原因:父类的功能,子类可能不需要或不满足。

  • 方法的重载

    ① 重载就是在同一个类中,有相同的函数名称,但形参不同的函数。
    ② 方法名必须相同,参数列表必须不同(参数个数不同,或类型不同,或参数排列顺序不同等)
    ③ 方法的返回类型可以相同也可以不同。
    ④ 仅仅返回类型不同不足以构成方法的重载。

三. 异常处理

  1. 异常两大类:Exception、Error。
  2. 若多个catch捕获异常,异常等级由小到大。 Finally可以不要,一定会执行,用于处理善后工作。
  3. 自定义异常类:类继承Exception。Throw new MyException():抛出自定义异常。

四. 集合

1. 集合的概念

① 集合是对象的容器。
集合不能直接存储基本数据类型,集合也不能直接存储java对象,集合当中存储的都是java对象的内存地址。(或者说集合中存储的是引用)
③ 集合类和集合接口都在java.util.* 包下。
④ 数组可存储基本类型和引用类型,集合只能存储引用类型。

2. Collection体系


3. Collection中常用方法

4. Iterator迭代器



 public static void main(String[] args) {
        //以下遍历方式/迭代方式,是所有collection通用的一种方式。 在Map集合中不能使用。
        //创建集合对象
        Collection c = new ArrayList();//后面的集合无所谓,主要是看前面的collection接口,怎么遍历/迭代。
        //添加元素
        c.add(120);
        c.add("hello");
        c.add(new Object());

        //对集合Collection进行遍历/迭代
        //第一步:获取集合对象的迭代器对象Iterator
        Iterator it = c.iterator();
        //第二步:通过上步获得的迭代器进行遍历
        /*
        * 迭代器对象iterator中的方法:
        * boolean hasNext(); 如果仍有元素可以迭代,返回true。
        * Object next(); 返回迭代的下一个元素。Object obj = it.next();
        * */
        System.out.println("集合中元素有:");
        while(it.hasNext()){
            Object o = it.next();
            System.out.println(o);
        }

    }

5. Contains方法


6. 集合转数组

7. Remove方法

8. List集合



9. 泛型





10. HashSet集合

11. TreeSet集合

12. Map接口常用方法



13. Map的遍历



14. HashMap






15. HashTable集合

16. Properties集合


17. TreeSet集合元素排序

方法一:类实现Comparable接口,重写compareTo方法。

//自定义类型实现comparable接口,放在TreeSet集合后实现排序。
//放在TreeSet集合中的元素需要实现java.lang.Comparable接口。
//并且实现compareTo方法,equals方法可以不写。
class Customer implements Comparable<Customer>{
    int age;

    public Customer(int age) {
        this.age = age;
    }

    //需要在这个方法中实现比较的逻辑或规则,有程序员指定。
    @Override
    public int compareTo(Customer o) {
        return this.age - o.age;//比较年龄大小
    }

    @Override
    public String toString() {
        return "Customer{" +
                "age=" + age +
                '}';
    }
}
方法二:编写一个类,实现Comparator接口,重写compare方法。

//给构造方法传递一个比较器
TreeSet<WuGui> wuGuis = new TreeSet<>(new WuGuiComparator());
//单独写一个比较器,实现java.util.Comparator接口。
//而Comparable是Java.lang包下的。
class WuGuiComparator implements Comparator<WuGui> {
    @Override
    public int compare(WuGui o1, WuGui o2) {
        return o1.age - o2.age;
    }
}

class WuGui{
    int age;

    public WuGui(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "WuGui{" +
                "age=" + age +
                '}';
    }
}
方式三:匿名内部类,不单独写构造器。
 
//第三种方式使用匿名内部类,不用单独写构造器,直接new接口
TreeSet<WuGui> wuGuis = new TreeSet<>(new Comparator<WuGui>() {
	  @Override
	  public int compare(WuGui o1, WuGui o2) {
	     return o1.age - o2.age;
	  }
});

18. 自平衡二叉树

19. Collections工具类



① HashSet输出的元素是无序的(存储自定义类型元素,需重写equals和hashcode方法,避免重复的问题),TreeSet输出的元素自动排序(实现接口,编写比较器)。
② HashMap中元素是没有顺序的;TreeMap中所有元素都是有某一固定顺序的。

五. IO流

1. 什么是IO

2. IO流的分类

3. IO流四大家族


4. FileInputStream和FileOutputStream

public class FileInputStreamTest03 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("tempfile");
            byte[] bytes = new byte[4];
            int readCount = 0;
            while ((readCount = fis.read(bytes)) != -1){
                System.out.print(new String(bytes,0,readCount));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            //文件不存在会自动新建
            //该语句执行时,会先清空文件内容,然后再写
//            fos = new FileOutputStream("testfile.txt");
            //以追加的方式在文件末尾写,不清空源文件
            fos = new FileOutputStream("testfile.txt",true);
            //开始写
            byte[] bytes = {97,98,99,100};
            //将byte数组全部写出
            fos.write(bytes); //abcd
            //将byte数组部分写出
            fos.write(bytes,0,2);//abcdab

            String s = "我是中国人";
            //将字符串转化为字符数组
            byte[] bs = s.getBytes();
            fos.write(bs);//abcdab我是中国人

            //输出流最后要刷新
            fos.flush();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

5. FileReader和FileWriter

   public static void main(String[] args) {
        FileReader reader = null;
        try {
            //创建文件字符流
            reader = new FileReader("tempfile");
            //开始读
            char[] chars = new char[4];
            //往char数组读
            reader.read(chars);
            for(char c : chars){
                System.out.print(c);
            }
/*            int readCount = 0;
            while((readCount = reader.read(chars)) != -1){
                System.out.print(new String(chars,0,readCount));
            }*/
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
 public static void main(String[] args) {
        FileWriter out = null;
        try {
//            out = new FileWriter("myfile.txt");
            out = new FileWriter("myfile.txt",true);
            char[] chars = {'我','是','中','国','人'};
            out.write(chars);
            out.write(chars,0,2);

            out.write("java工程师");
            out.write("\n");
            out.write("你好");

            out.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

6. 文件拷贝

    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("E:\\PPT模板\\An Improved DV-Hop Localization Algorithm Based on Selected Anchors.pdf");
            fos = new FileOutputStream("E:\\An Improved DV-Hop Localization Algorithm Based on Selected Anchors.pdf");

            byte[] bytes = new byte[1024*1024]; //每次最多读取1M
            int readCount = 0;
            while((readCount = fis.read(bytes)) != -1){
                fos.write(bytes,0,readCount);
            }
            //刷新
            fos.flush();
            //fos和fis关闭时,分开try。否则会影响另一个。


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //fos和fis关闭时,分开try。否则会影响另一个。
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
 public static void main(String[] args) {
        FileReader fr = null;
        FileWriter fw = null;
        try {

            fr = new FileReader("javase/src/com/IOStream/FileReaderTest01.java");
            fw = new FileWriter("fileReaderText.txt");

            char[] chars = new char[1024*512];
            int readCount = 0;
            while ((readCount = fr.read(chars)) != -1){
                fw.write(chars,0,readCount);
            }

            fw.flush();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

7. BufferedReader和BufferedWriter

 public static void main(String[] args) throws Exception{
        //当一个流的构造方法中需要一个流时,被传进来的流称为节点流
        //外部负责包装的这个流叫包装流或处理流
        FileReader reader = new FileReader("fileReaderText.txt");//节点流
        BufferedReader br = new BufferedReader(reader);//包装流

        //读行
        String s = null;
        while ((s = br.readLine()) != null){//读一行文本,不读换行符
            System.out.println(s);
        }

        br.close();//关闭包装流自动关闭节点流
    }
    public static void main(String[] args) throws Exception{

        //字节流
        FileInputStream in = new FileInputStream("fileReaderText.txt");
        //字节流转化为字符流
        InputStreamReader reader = new InputStreamReader(in);
        //BufferedReader构造器只能传字符流
        BufferedReader br = new BufferedReader(reader);

//        //以上合并写法:
//        BufferedReader br = new BufferedReader(new InputStreamReader
//                (new FileInputStream("fileReaderText.txt")));
        
        String s = null;
        while ((s = br.readLine()) != null){
            System.out.println(s);
        }

        br.close();
    }
    public static void main(String[] args) throws Exception{
//        BufferedWriter bw = new BufferedWriter(new FileWriter("copy.txt"));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter
                (new FileOutputStream("copy.txt",true)));//追加
        bw.write("hello");bw.write("\n");
        bw.write("houshuaixin");
        bw.flush();bw.close();
    }

8. PrintStream

    public static void main(String[] args) throws FileNotFoundException {
        //java.io.PrintStream:标准的字节输入流,默认输出至控制台
        //分开写,标准输出流不需要close()关闭
        PrintStream ps = System.out;
        ps.println("hello");ps.println("better");
        //联合写
        System.out.println("helloword");

        //改变标准输出流的输出方向
        //标准输出流不在指向控制台,指向“log”文件
        PrintStream printStream = new PrintStream(new FileOutputStream("log.txt"));
        //修改输出方向至“log.txt”文件
        System.setOut(printStream);
        System.out.println("helloword");
        System.out.println("hellokitty");
    }

六. 注解

//测试元注解
@MyAnnotation
public class TestAnnotation01 {
    public void test(){

    }
}

//定义一个注解
//Target 表示我们的注解可以用在那些地方
@Target(value = {ElementType.METHOD,ElementType.TYPE})

//Retention 表示我们的注解在什么地方还有效
// runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)

//Documented 表示是否将我们的注解生成在JAVAdoc中
@Documented

//Inherited 子类可以继承父类的注解
@Inherited

@interface MyAnnotation{

}

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口。

//自定义注解
public class TestAnnotation02 {
    //注解可以显式赋值,如果没有默认值,必须给注解赋值。
    @MyAnnotation2(name = "hou")
    public void test(){}
}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    //注解的参数:参数类型 + 参数名 + ();
    String name();
    //String name() default "";
    int age() default 15;
    String[] schools() default {"北大","清华"};
}

七. 反射

1. Class类

① Class本身也是一个类,Class对象只能由系统建立。
一个加载的类在JVM中只会有一个Class实例(Class对象只有一个)。
③ 一个Class对象对应的是一个加载到JVM中的一个 .class 文件。
通过Class实例可以获得一个类中所有被加载的结构。

2. Class类的实例

    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的Class对象
        Class c1 = Class.forName("Reflections.User");
        System.out.println(c1); //class Reflections.User

        Class c2 = Class.forName("Reflections.User");
        Class c3 = Class.forName("Reflections.User");

        //一个类在内存中只有一个Class对象
        //一个类被加载后,类的整个结构都会被封装在Class对象中
        System.out.println(c1.hashCode());//21685669
        System.out.println(c2.hashCode());//21685669
        System.out.println(c3.hashCode());//21685669
    }

3. Class类的创建方式

    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这个人是:"+person.name);

        //方式一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1);//class Reflections.Student

        //方式二:forname获得
        Class c2 = Class.forName("Reflections.Student");
        System.out.println(c2);//class Reflections.Student

        //方式三:通过类名.class获得
        Class c3 = Student.class;
        System.out.println(c3);//class Reflections.Student

        //方式四:基本内置类型的包装类有一个TYPE属性
        Class c4 = Integer.TYPE;
        System.out.println(c4);//int

        //获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);//class Reflections.Person
    }

4. 类加载器

    public static void main(String[] args) throws ClassNotFoundException {

        //获取系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父类加载器---》扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        //获取扩展类加载器的父类加载器---》根加载器(C、C++)
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1); //null

        //测试当前类是那个加载器加载的
        ClassLoader classLoader = Class.forName("Reflections.Test04").getClassLoader();
        System.out.println(classLoader);

        //测试JDK内置的类是谁加载的
        ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader1);
    }

5. 获取类运行时完整结构

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("Reflections.User");

        //获得类的名字
        System.out.println(c1.getName());//获得包名+类名
        System.out.println(c1.getSimpleName()); //获得类名

        //获得类的属性
        System.out.println("==========获得类的属性===========");
        Field[] fields = c1.getFields(); //只能找到public属性
        fields = c1.getDeclaredFields(); //找到所有属性
        for (Field field:fields){
            System.out.println(field);
        }

        //获得指定类型的属性
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        //获得类的方法
        System.out.println("==========获得类的方法===========");
        Method[] methods = c1.getMethods(); // 获得本类及其父类的所有public方法
        methods = c1.getDeclaredMethods(); // 获得本类的所有方法
        for(Method method:methods){
            System.out.println(method);
        }

        //获得指定方法(因重载问题,需出入指定方法的参数)
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        //获得类的构造器
        System.out.println("==========获得指定的构造器===========");
        Constructor[] constructors = c1.getConstructors();//本类的public
        constructors = c1.getDeclaredConstructors();//本类所有的

        //获得类的指定构造器
        Constructor deConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println(deConstructor);
        
    }

6. 动态创建对象调用方法和属性

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {

        //获得class对象
        Class c1 = Class.forName("Reflections.User");

        //创建一个对象   (针对有无参构造器)
        User user1 = (User) c1.newInstance(); //本质是调用了类的无参构造
        System.out.println(user1);

        //通过构造器创建对象   (针对没有无参构造器)
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user2 = (User)constructor.newInstance("hou", 45, 12);
        System.out.println(user2);

        //通过反射调用普通方法
        User user3 = (User) c1.newInstance();
        //通过反射获得一个方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        setName.invoke(user3,"hou");//invoke(对象,“传入的值”)
        System.out.println(user3.getName());

        //通过反射操作属性
        User user4 = (User)c1.newInstance();
        Field name = c1.getDeclaredField("name");
        //不能直接操作私有属性,需关闭程序的安全检测,属性(方法).setAccessible(true);
        name.setAccessible(true);
        name.set(user4,"侯帅鑫");
        System.out.println(user4.getName());
        
    }

八. 多线程

1. 概念

① 进程:是一次执行程序的过程,是系统资源分配的单位。
② 线程:一个进程通常包括若干个线程,一个进程中至少有一个线程,线程是CPU调度和执行的单位。
③ Main()为主线程,为系统的入口。

2. 创建线程的三种方式

① 自定义类继承Thread类,重写run方法,创建线程对象,调用start方法启动。
② 自定义类实现Runnable接口,重现run方法。
③ 自定义类实现Callable接口,重写call方法,需抛出异常。

public class TestThreads {
    public static void main(String[] args) {
        //方式一启动线程
        new MyThread1().start();

        //方式二启动线程
        new Thread(new MyThread2()).start();

        //方式三启动线程(了解)
        FutureTask<Integer> futureTask = new FutureTask<>(new MyThread3());
        new Thread(futureTask).start();

        Integer integer = null;
        try {
            integer = futureTask.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(integer);
    }
}

//1.继承Thread类
class MyThread1 extends Thread{
    @Override
    public void run() {
        System.out.println("MyThread1");
    }
}

//2.实现Runnable接口
class MyThread2 implements Runnable{

    @Override
    public void run() {
        System.out.println("MyThread2");
    }
}

//3.实现Callable接口
class MyThread3 implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("MyThread3");
        return 100;
    }
}

3. 静态代理

① 真实角色和代理角色都要实现同一个接口。
② 代理对象要代理真实角色。
③ 优点:代理对象可以做真实对象做不了的事,真实对象专注于做自己的事。

//静态代理
public class StaticProxy {
    public static void main(String[] args) {
        You you = new You();
        new Thread( ()-> System.out.println("我爱你")).start();
        new WeddingComp(new You()).HappyMarry();
    }
}

interface Marry{

    void HappyMarry();

}

//真是角色
class You implements Marry{

    @Override
    public void HappyMarry() {
        System.out.println("我要结婚了");
    }
}

//代理角色
class WeddingComp implements Marry{

    private Marry target;

    public WeddingComp(Marry target) {
        this.target = target;
    }

    @Override
    public void HappyMarry() {
        before();
        this.target.HappyMarry();
        after();
    }

    private void after() {
        System.out.println("收尾款");
    }

    private void before() {
        System.out.println("布置婚礼现场");
    }
}

4. Lambda表达式

public class TestLambda02 {

    public static void main(String[] args) {

        // Lambda表示简化
        ILove iLove = (int a)->{
            System.out.println("I Love You -->" + a);
        };

        //简化1.参数类型
        iLove = (a)->{
            System.out.println("I Love You -->" + a);
        };

        //简化2,简化括号
        iLove = a->{
            System.out.println("I Love You -->" + a);
        };

        //简化3,去掉花括号 ,仅适用于只有一行代码的情况
        iLove = a -> System.out.println("I Love You -->" + a);

        //前提接口为函数式接口
        //多个参数的类型名可同时省略,但括号必须保留

        iLove.love(2);
    }

}
interface ILove{  //函数式接口
    void love(int a);
}

5. 停止线程

//停止线程
//测试Stop
//1.建议线程正常停止--->利用次数,不建议死循环
//2.建议使用标志位---->设置一个标志位
//3.不要使用stop或者destroy等过时或者JDK不建议使用的方法
public class TestStop implements Runnable{

    //1.设置一个标识位
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while(flag){
            System.out.println("run....." + i++);
        }
    }

    //2.设置一个公开的方法停止线程
    public void stop(){
        this.flag = false;
    }

    public static void main(String[] args) {

        TestStop testStop = new TestStop();
        new Thread(testStop).start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("main--->"+i);
            if(i == 900){
                //转换标识位,停止线程
                testStop.stop();
                System.out.println("线程停止==========");
            }
        }

    }
}

6. 线程休眠

sleep时间达到后线程进入就绪状态,sleep可以模拟网络延时,倒计时等。每个对象都有一个锁,sleep不会释放锁。

//模拟倒计时
public class TestSleep {
    public static void main(String[] args) {

        //倒计时
        try {
            tenDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //打印当前系统时间
        Date startTime = new Date(System.currentTimeMillis());//获取系统当前时间

        while (true){
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
                startTime = new Date(System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

        //模拟倒计时
    public static void tenDown() throws InterruptedException {
        int num = 10;
        while(true){
            Thread.sleep(1000);
            System.out.println(num--);
            if(num<=0){
                break;
            }
        }
    }
}

7. 线程礼让

让当前正在执行的线程暂停,但不阻塞,将线程由运行状态转为就绪状态,让cpu重新调度,礼让不一定成功,看cpu心情。

//测试线程礼让
public class TestYield implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程开始");
        Thread.yield();//线程礼让,礼让不一定成功,看CPU心情
        System.out.println(Thread.currentThread().getName() + "线程停止");
    }

    public static void main(String[] args) {

        TestYield testYield = new TestYield();

        new Thread(testYield,"a").start();
        new Thread(testYield,"b").start();

    }
}

8. 线程强制执行

待该线程执行完后,再执行其他线程,使其他线程阻塞,可以想象为插队。

public class TestJoin implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 500; i++) {
            System.out.println("线程Vip。。。。。" + i);
        }
    }
    public static void main(String[] args) {
        //启动线程
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();
        //主线程
        for (int i = 0; i < 300; i++) {
            if(i==200){
                try {
                    thread.join();//线程插队
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("主线程。。。" + i);
        }
    }
}

9. 线程状态


10. 线程优先级

线程的优先级用数字表示,范围1-10。优先级低只是表示获得调度的概率低,并不是优先级低不会被调用,具体要看CPU的调度。改变优先级和获取优先级:setPriority(int xxx)、getPriority()。

//测试线程优先级
public class TestPriority {
    public static void main(String[] args) {
        //主线程的优先级
        System.out.println(Thread.currentThread().getName()+"--->"+Thread.currentThread().getPriority());

        MyPriority myPriority = new MyPriority();

        Thread t1 = new Thread(myPriority);
        Thread t2 = new Thread(myPriority);
        Thread t3 = new Thread(myPriority);
        Thread t4 = new Thread(myPriority);

        t1.setPriority(8);t1.start();

        t2.setPriority(1);t2.start();

        t3.setPriority(Thread.MAX_PRIORITY);t3.start();

        t4.setPriority(6);t4.start();
    }
}

class MyPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"--->"+Thread.currentThread().getPriority());
    }
}

11. 守护线程

线程分为用户线程和守护线程。虚拟机必须确保用户线程执行完毕,不用等待守护线程执行完毕。

public class TestDaemon {
    public static void main(String[] args) {
        God god = new God();
        Your your = new Your();

        Thread thread = new Thread(god);
        thread.setDaemon(true); //默认是false表示用户线程,正常的线程都是用户线程。
        thread.start();//上帝守护线程启动,虽然god为死循环,但是用户线程结束后,它也结束

        new Thread(your).start();//你,用户线程启动
    }

}

//上帝
class God implements Runnable{

    @Override
    public void run() {
        while(true){
            System.out.println("上帝守护着你");
        }
    }
}
//你
class Your implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("开心每一天");
        }
        System.out.println("=================goodbye==================");
    }
}

12. 线程同步机制

多个线程操作同一个资源。线程同步形成的条件:队列+锁。锁机制:synchronized。
Synchronized默认锁的是this。锁的对象就是变化的量,需要增删改查的对象。
同步块:synchronized(obj){ }

//不安全的买票方案
public class UnSafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket station = new BuyTicket();

        new Thread(station,"aa").start();
        new Thread(station,"bb").start();
        new Thread(station,"cc").start();
    }

}

class BuyTicket implements Runnable{

    private int ticketNums = 10;
    boolean flag = true;
    @Override
    public void run() {
        while(flag){
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //同步方法,安全的
    //public synchronized void buy() throws InterruptedException
    public  void buy() throws InterruptedException {
        if(ticketNums<=0){
            flag = false;
            return;
        }
        //模拟延时
        Thread.sleep(100);
        System.out.println(Thread.currentThread().getName() + "拿到----->" + ticketNums--);
    }
}

13. 死锁

死锁产生的条件:
① 互斥条件:一个资源每次只能被一个进程使用。
② 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
③ 不剥夺条件:进程已获得的资源,在未使用完前,不能强行剥夺。
④ 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

//测试死锁:多个线程互相抱着对方需要的资源,形成僵持
public class TestDeadLock {
    public static void main(String[] args) {

        Makeup g1 = new Makeup(0, "灰姑娘");
        Makeup g2 = new Makeup(1, "白雪公主");

        g1.start();
        g2.start();

    }
}

//口红
class LipStick{

}

//镜子
class Mirror{

}

class Makeup extends Thread {
    //需要的资源只有一份,用static来保证只有一份
    static LipStick lipStick = new LipStick();
    static Mirror mirror = new Mirror();

    int choice;//选择
    String name;//使用化妆品的人

    public Makeup(int choice, String name) {
        this.choice = choice;
        this.name = name;
    }

    @Override
    public void run() {
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //化妆,互相持有对方的锁,就是需要拿到对方的资源
    //避免死锁
    private void makeup() throws InterruptedException {
        if (choice == 0) {
            synchronized (lipStick) {
                System.out.println(this.getName() + "获得口红的锁");
                Thread.sleep(2000);
            }
            synchronized (mirror) {
                System.out.println(this.getName() + "获得镜子的锁");
            }
        } else {
            synchronized (mirror) {
                System.out.println(this.getName() + "获得镜子的锁");
                Thread.sleep(2000);
            }
            synchronized (lipStick) {
                System.out.println(this.getName() + "获得口红的锁");
            }
        }
    }
}

14. Lock(锁)


public class TestLock {
    public static void main(String[] args) {
        Buyticket buyticket = new Buyticket();

        new Thread(buyticket).start();
        new Thread(buyticket).start();
        new Thread(buyticket).start();

    }
}

class Buyticket implements Runnable{

    int tickeNums = 10;
    //定义lock锁
    private final ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while(true){

            try {
                lock.lock(); //加锁
                if(tickeNums>0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(tickeNums--);
                }else{
                    break;
                }
            }finally {
                lock.unlock();//解锁
            }

        }

    }
}

15. 线程池

//测试线程池
public class TestPool {
    public static void main(String[] args) {
        //1.创建服务,创建线程池
        //newFixedThreadPool  参数为:线程池大小
        ExecutorService service = Executors.newFixedThreadPool(10);
        //执行
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());

        //2.关闭链接
        service.shutdown();
    }
}

class MyThread implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

16. wait和notify

  • tt.wait(): 让正在tt对象上活动的线程进入等待状态。
  • wait(): 无限期等待,直至被唤醒。
  • tt.notify():唤醒正在tt对象上等待的线程。
  • tt.notifyAll(): 唤醒tt对象上处于等待的所有线程。

17. 生产者消费者

package multiThreads.PCModel;

public class TestBestPC {
    public static void main(String[] args) {
        Resources resources = new Resources();
        Thread threadProduct = new Thread(new Producers(resources));
        Thread threadConsume = new Thread(new Consumers(resources));
        threadProduct.setName("Producers");
        threadConsume.setName("Consumers");
        threadProduct.start();
        threadConsume.start();
    }
}

//资源
class Resources{

    //当前资源的数量
    int num = 0;
    //当前资源的上限
    int size = 100;

}

//消费者
class Consumers implements Runnable{

    private Resources resources;

    public Consumers(Resources resources) {
        this.resources = resources;
    }

    @Override
    public void run() {
        while (true){
            synchronized (resources){
                if(resources.num == 0){
                    System.out.println("========消费者等待=======");
                    try {
                        resources.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                resources.num--;
                System.out.println("消费者:"+Thread.currentThread().getName()+",剩余资源"+resources.num);
                resources.notify();
            }
        }
    }
}

//生产者
class Producers implements Runnable{

    private Resources resources;

    public Producers(Resources resources) {
        this.resources = resources;
    }

    @Override
    public void run() {
        while (true){
            synchronized (resources){
                if(resources.num == resources.size){
                    System.out.println("========生产者等待=======");
                    try {
                        resources.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                resources.num++;
                System.out.println("生产者:"+Thread.currentThread().getName()+",剩余资源"+resources.num);
                resources.notify();
            }
        }
    }
}

更多推荐

Java基础知识点汇总