Java知识点复习

Java中的多态,子类调用父类方法

java 复制代码
public static void main(String[] args) {
    /* Child 继承于 Parent */
    Parent parent = new Child(); // 只能调用父类和子类共有的方法,并且子类会覆盖父类的方法
    Child child = new Child(); // 可以调用子类特有的方法
    /*非静态方法的调用遵循动态绑定规则:运行时会根据引用变量所指向的 "实际对象类型" 来决定调用哪个类的方法
    * 如果play方法是 static 修饰的,那么就会调用父类的 play 方法*/
    parent.play(); // Calls Parent's play method
    child.play2(); // child 调用自己独有而父类没有的方法 play2
}

下面演示了通过反射获取父类实例,然后调用play方法(play是私有的,子类重写了play方法):

java 复制代码
Class<?> aClass = Class.forName("com.example.tipsdemo.classExtend.Parent");
System.out.println(aClass.getName());
Constructor<?> constructor = aClass.getConstructor();
Parent o = (Parent) constructor.newInstance();
o.sayHello();
// 通过反射访问父类中的私有方法,而不是子类中的私有方法,这一点要明确,因为我们反射的目标就是父类
Method play = aClass.getDeclaredMethod("play");
play.setAccessible(true);
play.invoke(o);

最终调用的还是父类的play()方法,因为我们反射的目标是父类,所以就会调用父类的play()方法

单例模式的饿汉和懒汉是什么

单例模式有两种实现方式,一种是饿汉一种是懒汉,他们的区别就是实例创建的时机不同,饿汉式类初始化的时候就会创建一个单例的对象,这个对象属于类信息。因为指挥创建一次所以也就避免了线程安全的问题。懒汉式是在使用的时候创建单例对象,存在线程安全问题,我们可以通过双重锁检查的方式避免并发问题,具体的代码如下:

java 复制代码
// 饿汉
public class Singleton {
    // 1. 私有静态变量:类加载时直接初始化实例
    private static final Singleton INSTANCE = new Singleton();

    // 2. 私有构造器:阻止外部通过 new 创建实例
    private Singleton() {}

    // 3. 公共静态方法:返回唯一实例
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
java 复制代码
// 懒汉
public class Singleton {
    // 1. 用 volatile 防止指令重排序导致的半初始化问题
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) { // 2. 第一次检查:未加锁,提高效率
            synchronized (Singleton.class) { // 加锁
                if (instance == null) { //3.  第二次检查:防止多线程同时通过第一次检查
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

为什么要进行第二次的锁检查? 比如有两个线程A和B,A和B在判断instance==null的时候都返回的是true,那么他们就都会进入同步代码块,比如A先进入synchronized代码块,然后B阻塞在synchronized代码块之外,当A创建完成实例之后就会释放锁,那么B就会进入synchronized代码块,此时已经有一个实例了,B不应该再次创建实例,但是如果我们不添加第二次检查,即instancee==null,就会再次创建实例,这是不期望的。所以应该在同步代码块中再加一次检查。

final、finally、finalizer

名称 类型 核心作用 常见场景
final 修饰符 限制类、方法、变量的可变性(不可继承 / 重写 / 修改) 定义常量、禁止继承 / 重写、线程安全等
finally 异常处理块 确保关键代码(如资源释放)必定执行 搭配 try/catch 释放文件、数据库连接等
finalize() 实例方法 对象被 GC 前的清理操作(已过时) 早期用于释放非 Java 资源(不推荐使用)

两个线程交替执行

java 复制代码
package com.example.tipsdemo.pool;

import ch.qos.logback.classic.pattern.ClassOfCallerConverter;

public class Poll2 {
    public static void main(String[] args) {
        Task01 task01 = new Task01();
        Thread thread_1 = new Thread(task01,"thread_1");
        Thread thread_2 = new Thread(task01,"thread_2");
        thread_1.start();
        thread_2.start();

    }

    static class Task01 implements Runnable {
        private static final Object lock = new Object();
        private static int sum = 0;
        private static int count = 0; // 总执行次数计数器(控制总次数为1000)
        private static boolean flag = true;
        @Override
        public void run() {
            while(count<1000){
                synchronized (lock){
                    while((flag && Thread.currentThread().getName().equals("thread_1")) || (!flag && Thread.currentThread().getName().equals("thread_2"))){
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    sum++;
                    System.out.printf("当前线程:"+Thread.currentThread().getName()+ ", count=" + count +"sum = " + sum + "\n");
                    flag = !flag;
                    count++;
                    lock.notify();



                }
            }
        }
    }
}

三个线程交替执行

java 复制代码
package com.example.tipsdemo.pool;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Poll3 {
    private static int count = 0;
    static ReentrantLock lock = new ReentrantLock();
    static Condition c1 = lock.newCondition();
    static Condition c2 = lock.newCondition();
    static Condition c3 = lock.newCondition();
    static int turn = 1;
    public static void main(String[] args) {


        Thread thread1 = new Thread(() -> {
            runTask(1,c1,c2);
        }, "A");
        Thread thread2 = new Thread(() -> {
            runTask(2,c2,c3);
        }, "B");
        Thread thread3 = new Thread(() -> {
            runTask(3,c3,c1);
        }, "C");
        thread1.start();
        thread2.start();
        thread3.start();


    }


    public static void runTask(int myTurn, Condition curCondition, Condition nextCondition) {
        while (count < 100) {
            lock.lock();
            try {
                while (turn != myTurn) {
                    curCondition.await();
                }
                System.out.println("当前线程是:" + Thread.currentThread().getName() +",turn = " + turn + ",myTurn = " + myTurn);
                count++;
                turn = (turn + 1);
                if(turn >3) turn =1;
                nextCondition.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}
相关推荐
Postkarte不想说话3 小时前
Cisco配置BGP
后端
小帅说java3 小时前
【Java开发】Java热门框架深入开发第11篇:学习目标,一、SpringBoot简介【附代码文档】
javascript·后端
CodeSheep4 小时前
JetBrains官宣,又一个IDE可以免费用了!
前端·后端·程序员
间彧4 小时前
SpringBoot和Servlet的联系
后端
间彧4 小时前
Spring Boot的DispatcherServlet是如何封装和扩展原生Servlet功能的?
后端
无名之辈J4 小时前
GC Overhead 的排查
后端
道19935 小时前
50 台小型无人车与50套穿戴终端 5 公里范围内通信组网方案深度研究
java·后端·struts
间彧5 小时前
Spring Boot中,拦截器和Spring AOP有什么区别
后端
JaguarJack5 小时前
PHP 开发者应该理解的 Linux 入门权限指南
后端·php