服务端开发Java面试复盘篇1

news2024/9/30 15:36:46

上周投了一些简历,约了8-9家面试,其中完成了3家的第一轮面试,由于面试的是Java 的实习生,感觉问的题目都比较基础,不过有些问题回答的不是很好,在这里对回答的不太好的题目做一下总结和复盘。

目录

一、后端开发Java面试复盘

1.1、23种设计模式

1.2、数据库(MySQL)的索引失效情况

1.3、线程池的使用

1.4、ConcurrentHashMap的使用及底层原理

1.5、Spring的传递依赖问题

1.6、MySQL事务的四种隔离级别


一、后端开发Java面试复盘

1.1、23种设计模式

设计模式:就是代码设计经验的总结。使用设计模式可以提高代码的可靠性和可重用性。

设计模式共有23中,整体分为3大类,如下:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式

设计模型有6大原则,具体如下

1)开放封闭原则:尽量通过扩展软件实体应对需求的改变,而不是修改原有代码

2)里氏代换原则:使用的基类可以在任何地方使用继承的字类,完美的替换基类

3)依赖倒转原则:即面向接口编程,依赖抽象而不依赖具体

4)接口隔离原则:使用多个隔离的接口替代单个接口,降低耦合

5)迪米特法则:一个类尽量减少对其他类的依赖

6)单一职责:一个方法尽量只负责一件事

单例模式,分为饿汉模式和懒汉模式,都是每个类中只创建一个实例,并提供全局访问点来访问这个实例。饿汉模型是线程安全的,懒汉模式线程不安全,需要使用双重检测锁保证线程安全,具体的Java代码实现如下:

/**
 * 单例模式:确保每个类只有一个实例,并提供全局访问点来访问这个实例
 */
//饿汉模式:线程安全
class Singleton1 {
    private static Singleton1 instance = new Singleton1() ;
    public Singleton1 getInstance(){
        return instance ;
    }
}

//懒汉模式:线程不安全,需要通过双重检查锁定机制控制
class Singleton2{
    private static Singleton2 instance2 = null ;
    public Singleton2 getInstance2(){
        if(instance2 == null){
            instance2 = new Singleton2() ;
        }
        return instance2 ;
    }
}
//使用双重检查锁的方式保重线程安全
class Singleton3{
    //使用双重检查进行初始化的实例必须使volatile关键字修饰
    private volatile static Singleton3 instance3 = null ;
    public Singleton3 getInstance3(){
        if(instance3 == null){
            synchronized (Singleton3.class){
                if(instance3 == null){
                    instance3 = new Singleton3();
                }
            }
        }
        return instance3 ;
    }
}
public class Main {
    public static void main(String[] args) {
        Singleton1 singleton1 = new Singleton1() ;
        Singleton1 singleton2 = new Singleton1() ;
        Singleton2 singleton21 = new Singleton2() ;
        Singleton2 singleton22 = new Singleton2() ;
        Singleton1 instance1 = singleton1.getInstance();
        Singleton1 instance2 = singleton2.getInstance();
        Singleton2 instance21 = singleton21.getInstance2();
        Singleton2 instance22 = singleton22.getInstance2();
        System.out.println(instance1 == instance2);
        System.out.println(instance21 == instance22);
    }
}

下面在了解一下工厂模式和代理模式。

工厂模式是一种创建对象的最佳方式,在创建对象时不对客户端暴露创建逻辑,通过使用一个共同的接口来指向新创建的对象,实现创建者和调用者的分离,工厂模式分为简单工厂,工厂方法和抽象工厂。我们熟知的Spring的IOC容器使用工厂模式创建Bean,只需要交给Bean进行管理即可,这样我们在业务层调接口层的方法时候就不需要再new了,可以直接注入。

1)简单工厂模式:也称为静态工厂方法,可以根据参数的不同返回不同类的实例,简单工厂模式专门定义一个类来负责创建其它类的实例,被创建的实例通常都有共同的父类。

首先创建工厂:

public interface Car {
    public void run() ;
}

定义工厂中的两个产品:

public class Car1 implements Car {
    @Override
    public void run() {
        System.out.println("我是小汽车");
    }
}
public class Bus implements Car {
    @Override
    public void run() {
        System.out.println("我是大卡车");
    }
}

创建核心工厂类,决定调用工厂中的哪一种方法,具体如下:


/**
 * 创建工厂类,在工厂类中决定调用哪一种产品
 */
public class CarFactory {
    public static Car createCar(String name){

        if("小汽车".equals(name)){
            return new Car1() ;
        }
        if("大卡车".equals(name)){
            return new Bus() ;
        }
        return null ;
    }

}

演示创建共创对象,并调用工厂中的产品,具体如下:

/**
 * 演示简单工厂
 */
public class Factory1 {
    public static void main(String[] args) {
        //通过工厂类创建工厂对象
        Car car = CarFactory.createCar("小汽车");
        Car car1 = CarFactory.createCar("大卡车");
        //调用工厂方法
        car.run();
        car1.run();
    }
}
  • 优点:简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
  • 缺点:很明显工厂类集中了所有实例的创建逻辑,容易违反GRASPR的高内聚的责任分配原则。

2)工厂方法模式:也称多态性工厂模式,核心的工厂类不在负责所有产品实例的创建,而是将具体的创建交给具体的子类去做,该核心类成为一个抽象工厂角色,仅仅给出具体工厂字类必须实现的接口,而不涉及具体哪一个产品被实例化。

首先是创建工厂和工厂的两个产品,具体如下:

public interface Car {
    public void run() ;
}


public class Car1 implements Car {
    @Override
    public void run() {
        System.out.println("我是小汽车");
    }
}


public class Bus implements Car {
    @Override
    public void run() {
        System.out.println("我是大卡车");
    }
}

然后创建工厂方法调用接口,并创建工厂实例。

/**
 * 创建创建工厂方法调用接口,所有工厂产品需要实现该接口,并重写接口方法
 */
public interface Factorys {
    Car createFactory() ;
}


public class CarF implements Factorys {
    @Override
    public Car createFactory() {
        return new Car1() ;
    }
}

public class BusF implements Factorys {
    @Override
    public Car createFactory() {
        return new Bus() ;
    }
}

最后演示工厂方法的实现。

public class Factory2 {
    public static void main(String[] args) {
        Car car = new CarF().createFactory();
        Car car1 = new BusF().createFactory();
        car.run() ;
        car1.run() ;
    }
}

3)抽象工厂模式:即工厂的工厂 ,抽象工厂可以创建具体工厂,由具体工厂来生产具体产品。

首先创建第一个子工厂及其实现类,如下:

/**
 * 创建第一个工厂接口及其实现类
 */
public interface A  {
    void run() ;
}
class CarA implements A{
    @Override
    public void run() {
        System.out.println("奔驰");
    }
}
class CarB implements A{
    @Override
    public void run() {
        System.out.println("宝马");
    }
}

创建第2个子工厂及其实现类,具体如下:

public interface B {
    void run() ;
}
class Animal1 implements B{

    @Override
    public void run() {
        System.out.println("狗");
    }
}
class Animal implements B{

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

创建一个总工厂及其实现类,由总工厂的实现类决定调用哪个工厂的哪个实例。

/**
 * 总工厂,包含创建工厂工厂的接口
 */
public interface TotalFactory {
    A createA() ;
    B createB() ;
}

/**
 * 总工厂的实现类,决定创建哪个工厂的哪个实例
 */
class TotalFactoryImpl implements TotalFactory{

    @Override
    public A createA() {
        return new CarA() ;
    }

    @Override
    public B createB() {
        return new Animal1();
    }
}

最后演示抽象工厂模式,如下:

public class Test {
    public static void main(String[] args) {
        A a = new TotalFactoryImpl().createA();
        B b = new TotalFactoryImpl().createB();
        a.run();
        b.run() ;
    }
}

下面我们看一下代理模式,我们正常在Spring会接触到代理模式。我们先了解一下什么是代理。

  • 通过代理控制对象的访问,可以在这个对象调用方法之前、调用方法之后去处理/添加新的功能。(也就是AOP的实现)
  • 代理在原有代码乃至原业务流程都不修改的情况下,直接在业务流程中切入新代码,增加新功能,这也和Spring的(面向切面编程)很相似

我们常见的代理模式分为3种,即静态代理,JDK动态代理和CGLIB动态代理。

静态代理:简单代理模式,是动态代理的理论基础。常见使用在代理模式。
JDK 代理 : 基于接口的动态代理技术·:利用拦截器(必须实现invocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理,从而实现方法增强。
CGLIB代理:基于父类的动态代理技术:动态生成一个要代理的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截技术拦截所有的父类方法的调用,顺势织入横切逻辑,对方法进行增强。

1)静态代理

我们首先看如下一个接口类,如何在不改变接口类的基础上,在接口方法中开启和关闭事务,我们可以使用静态代理的方式。


public interface UserDao {
    void save() ;
}

class UserDaoImpl implements UserDao{

    @Override
    public void save() {
        System.out.println("添加数据");
    }
}
public class Test2 {
    public static void main(String[] args) {
        UserDaoImpl userDao = new UserDaoImpl();
        userDao.save();
    }
}

下面是静态代理实现的代码,如下:

public class UserDaoProxy extends UserDaoImpl {
    public UserDaoImpl userDao ;
    public UserDaoProxy(UserDaoImpl userDao){
        this.userDao = userDao ;
    }

    @Override
    public void save() {
        System.out.println("开启事务");
        super.save();
        System.out.println("关闭事务");
    }
}
public class Test2 {
    public static void main(String[] args) {
        UserDaoImpl userDao = new UserDaoImpl();
        UserDaoProxy userDaoProxy = new UserDaoProxy(userDao);
        userDaoProxy.save();

    }
}

2)下面看一下JDK动态代理,它是基于接口的动态代理技术,用拦截器(必须实现invocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理,从而实现方法增强。

首先编写可以重复使用的代理类,如下,可以重复使用,不像静态代理那样每次都要重复编写带泪类,具体如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class InvocationHandlerImpl implements InvocationHandler {
    //通过构造方法传入目标对象
    public Object target ;
    InvocationHandlerImpl(Object target){
        this.target = target ;
    }
    /**
     * 动态代理实际运行的代理方法,以反射的方式创建对象
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始");
        Object invoke = method.invoke(target, args);
        System.out.println("结束");
        return invoke ;
    }
}
public class Test2 {
    public static void main(String[] args) {
        //已构造方法的方式传入被代理的对象
        UserDaoImpl userDaoImpl = new UserDaoImpl() ;
        InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(userDaoImpl);
        //类加载器
        ClassLoader classLoader = userDaoImpl.getClass().getClassLoader();
        Class<?>[] interfaces = userDaoImpl.getClass().getInterfaces();
        UserDao proxyInstance = (UserDao)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        proxyInstance.save();

    }
}

3)最后我们看一下CGLIB动态代理,基于父类的动态代理技术:动态生成一个要代理的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截技术拦截所有的父类方法的调用,顺势织入横切逻辑,对方法进行增强。

简单地说就是实现MethodInterceptor接口并重写intercept()方法实现动态代理。

1.2、数据库(MySQL)的索引失效情况

1)查询条件有or关键字(必须所有查询条件都有索引)

2)模糊查询like以%开头

3)索引列上的条件where部分涉及计算或者函数

4)复合索引缺少左列字段

5)数据库认为全表扫描比索引更高效

1.3、线程池的使用

创建线程常见的几种方法包括继承Thread类并重写run()方法,实现Runnable()接口或实现Collable()等。一般来说,我们使用传统的方法每次创建和销毁线程的开销都比较大,故我们可以使用线程池的方式,减小开销。

使用线程池主要有如下的优势:

1)提高效率,创建好一定数量的线程放在池中,等需要使用的时候就从池中拿一个,这要比需要的时候创建一个线程对象要快的多。
2)减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
3)提升系统响应速度,假如创建线程用的时间为T1,执行任务用的时间为T2,销毁线程用的时间为T3,那么使用线程池就免去了T1和T3的时间。
 

Executors类(并发包)提供了4种创建线程池方法,这些方法最终都是通过配置ThreadPoolExecutor的不同参数,来达到不同的线程管理效果。

推荐通过 new ThreadPoolExecutor() 的写法创建线程池,这样写线程数量更灵活开发中多数用这个类创建线程。

该类包含如下核心参数:核心线程数,最大线程数,闲置超时时间,超时时间的单位,线程池中的任务队列,线程工厂,拒绝策略。

 

最后一个参数为拒绝策略,一半包含四种拒绝策略,如下:

1. AbortPolicy

当任务添加到线程池中被拒绝时,直接丢弃任务,并抛出RejectedExecutionException异常

2. DiscardPolicy

当任务添加到线程池中被拒绝时,丢弃被拒绝的任务,不抛异常

3. DiscardOldestPolicy

当任务添加到线程池中被拒绝时,丢弃任务队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中

 4. CallerRunsPolicy

被拒绝任务的处理程序,直接在execute方法的调用线程中运行被拒绝的任务。

总结:就是被拒绝的任务,直接在主线程中运行,不再进入线程池。

下面看一个demo,创建线程池,并设置最大线程数目为2,设置拒绝策略为CallerRunsPolicy。

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Test {
    public static void main(String[] args) {
        // 创建单线程-线程池,任务依次执行
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 2,
                60, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(2),
                new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 0; i < 10; i++) {
            //创建任务
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName());
                }
            };
            // 将任务交给线程池管理
            threadPoolExecutor.execute(runnable);
        }
    }
}

1.4、ConcurrentHashMap的使用及底层原理

Map包括HashMap和HashTable。

HashMap性能高,但不是线程安全:
HashMap的性能比较高,但是HashMap不是线程安全的,在并发环境下,可能会形成环状链表导致get操作时,cpu空转,所以,在并发环境中使用HashMap是非常危险的。

HashTable是线程安全的,但性能差:
HashTable和HashMap的实现原理几乎一样,差别:HashTable不允许key和value为null。
HashTable是线程安全的,但是HashTable线程安全的策略实现代价却比较大,get/put所有相关操作都是synchronized的,这相当于给整个哈希表加了一把大锁,多线程访问时候,只要有一个线程访问或操作该对象,那其他线程只能阻塞,这就导致性能比较低。

ConcurrentHashMap是线程安全的且性能高:

JDK1.7版本: 容器中有多把锁,每一把锁锁一段数据,这样在多线程访问时不同段的数据时,就不会存在锁竞争了,这样便可以有效地提高并发效率。

JDK1.8版本:做了2点修改,取消segments字段,直接采用transient volatile HashEntry<K,V>[] table保存数据,采用table数组元素作为锁,从而实现了对每一行数据进行加锁,并发控制使用Synchronized和CAS来操作将原先table数组+单向链表的数据结构,变更为table数组+单向链表+红黑树的结构。
 

1.5、Spring的传递依赖问题

maven环境存在的依赖冲突问题,可以在pom文件中使用<exlusions>标签排除依赖,主动断开依赖的资源,被排除的资源无需指定版本。

在Spring中解决循环依赖问题,可以使用三级缓存,三级缓存如下:

 

1.6、MySQL事务的四种隔离级别

MySQL支持四种事务隔离级别,默认的事务隔离级别为repeatable read,Oracle数据库默认的隔离级别是read committed。

四种隔离级别分别为读未提交,读已提交,可重复读, 序列化/串行化。其中,读未提交是最低的隔离级别,序列化隔离级别最高。

1.读未提交(read uncommitted):没有提交就读取到了。
2.读已提交(read committed):已经提交的才能读取。
3.可重复读(repeatable read):事务结束之前。永远读取不到真实数据,提交了也读取不到,读取的永远都是最初的数据,即假象。
4.序列化(serializable):表示事务排队,不能并发,每次读取的都是最真实的数据。

同时运行多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题。
1-脏读:对于两个事务T1和T2,T1读取了已经被T2更新但还没有提交的字段,之后,若T2回滚,则T1读取的数据就是临时且无效的。
2-不可重复读:对于两个事务T1和T2,T1读取了该字段,但是T2更新了该字段,T1再次读取这个字段,值就不同了。
3-幻读:对于两个事务T1和T2,T1从表中读取了一些字段,T2在表中插入了一些新的行,T1再次读取该表发现多几行。

read uncommitted:可以出现脏读,幻读,不可重复读。
read committed:避免脏读,出现幻读和不可重复读。
repeatable read:避免脏读和不可重复读,出现幻读。
serializable:避免脏读,幻读,不可重复读。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/338423.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据库】 mysql用户授权详解

目录 MySQL用户授权 一&#xff0c;密码策略 1&#xff0c;查看临时密码 2&#xff0c;查看数据库当前密码策略&#xff1a; 二&#xff0c; 用户授权和撤销授权 1、创建用户 2&#xff0c;删除用户 3&#xff0c;授权和回收权限 MySQL用户授权 一&#xff0c;密码策略…

Https 协议超强讲解(一)

都说Https协议非常安全&#xff0c;那为什么还是会被抓包呢&#xff1f;抓包后会影响什么吗&#xff1f; HTTPS协议 随着 HTTPS 建站的成本下降&#xff0c;现在大部分的网站都已经开始用上 HTTPS 协议。大家都知道 HTTPS 比 HTTP 安全&#xff0c;也听说过与 HTTPS 协议相关…

ChatGPT vscode中文插件

方式一和方式二只需要做一个就行 方式一&#xff1a;直接购买账号&#xff0c;购买渠道请自行寻找。 快捷键打开命令面板(ctrlshiftp 或者 commandshiftp) 输入 ChatGPT 然后选择 ChatGPT: 切换成国内/国外模式(将会重启VSCode) 命令来切换到国外模式此时会弹出一个输入框&am…

12.hadoop系列之MapReduce分区实践

本文我们学习MapReduce默认分区以及自定义分区实践 当我们要求将统计结果按照条件输出到不同文件(分区)&#xff0c;比如按照统计结果将手机归属地不同省份输出到不同文件中(分区) 1.默认Partitioner分区 public class HashPartitioner<K, V> extends Partitioner<…

ChatGPT已接入微软必应Bing搜索?如何进入新必应候补名单抢先体验

文章目录1. 前提2. 开始申请3. 直接使用ChatGPT1. 前提 Edge浏览器微软账号科学上网工具 2. 开始申请 进入新必应网址&#xff1a;https://www.bing.com/new&#xff0c;点击加入等待列表。 此时会弹出微软的登录界面&#xff0c;登录自己的微软账号即可&#xff0c;建议使用…

【C++/QT】QT5.6解析Excel教程(qtxlsx)

这里写目录标题【背景】【下载qtxlsx】【安装perl】【编译qtxlsx】【添加模块】【使用qtxlsx】【背景】 新接触QT&#xff0c;很多东西都不会&#xff0c;刚接触一个解析Excel的demo&#xff0c;记录一下安装、编译、解析Excel的过程 【下载qtxlsx】 在解析之前&#xff0c;…

多传感器融合定位十-基于滤波的融合方法Ⅰ其二

多传感器融合定位十-基于滤波的融合方法Ⅰ其二3. 滤波器基本原理3.1 状态估计模型3.2 贝叶斯滤波3.3 卡尔曼滤波(KF)推导3.4 扩展卡尔曼滤波(EKF)推导3.5 迭代扩展卡尔曼滤波(IEKF)推导4. 基于滤波器的融合4.1 状态方程4.2 观测方程4.3 构建滤波器4.4 Kalman 滤波实际使用流程4…

【Python学习笔记】25.Python3 输入和输出(1)

前言 在前面几个章节中&#xff0c;我们其实已经接触了 Python 的输入输出的功能。本章节我们将具体介绍 Python 的输入输出。 输出格式美化 Python两种输出值的方式: 表达式语句和 print() 函数。 第三种方式是使用文件对象的 write() 方法&#xff0c;标准输出文件可以用…

Linux手工创建新用户

准备工作&#xff08;配置流程的理解&#xff09; Linux中useradd命令即一系列文件操作的结合体&#xff0c;所以我们可以通过查看useradd命令来确认我们手工创建新用户需要完成的文件配置 找到man useradd中涉及的文件部分 对于手工创建用户有用的文件&#xff1a; /etc/pas…

jvm学习的核心(五)---垃圾回收算法和常见垃圾回收器

文章目录1.垃圾回收算法**1.1. 标记阶段****1.2. 清除阶段**1.2.1.标记清除算法1.2.2.标记复制算法1.2.3.标记整理算法1.3.引用2.常见的垃圾回收器2.1.Serial回收器2.2.ParNew回收器2.3.Parallel回收器2.4.CMS回收器<font color red>2.5.G1垃圾回收器ZGC回收器&#xff…

2月面经:真可惜...拿了小米的offer,字节却惨挂在三面

我是2月份参加字节跳动和华为的面试的&#xff0c;虽然我只拿下了小米的offer&#xff0c;但是我自己也满足了&#xff0c;想把经验分享出来&#xff0c;进而帮助更多跟我一样想进大厂的同行朋友们&#xff0c;希望大家可以拿到理想offer。 自我介绍 我是16年从南京工业大学毕…

java ssm idea高校图书借阅管理系统设计2z87z

本论文是以构建高校图书管理系统设计为目标&#xff0c;使用 jsp制作&#xff0c;由前台用户图书借阅、后台管理员图书分类两大部分组成。着重论述了系统设计分析&#xff0c;系统的实现&#xff08;用户注册模块&#xff0c;用户登录&#xff0c;用户图书借阅模块&#xff0c;…

ONNXRUNTUIME c++使用与相关资料(暂记)

下面的教程是在linux系统上运行的&#xff0c;如果想在windows系统上运行&#xff0c;可以看官方链接或中文教程https://bbs.huaweicloud.com/blogs/335706&#xff0c;官方链接中有完整的VS的带.sln的项目。 ONNXRUNTUIME OPENCV不支持某些算子(挤压层在opencv 中不支持) 安…

开关电源环路稳定性分析(10)——OPA和OTA型补偿器传递函数

大家好&#xff0c;这里是大话硬件。 在前面9讲的内容中将开关电源环路分析进行了梳理&#xff0c;我相信很多人即使都看完了&#xff0c;应该还是不会设计&#xff0c;而且还存在几个疑问。比如我随便举几个&#xff1a; 开关电源的带宽怎么设定&#xff1f;开关电源精度和什…

IDEA下java程序的调试(简易实例图示版)

在线排版不太好看&#xff0c;介意的读者可下载word下来看&#xff1a;https://download.csdn.net/download/xijinno1/87441301IDEA下java程序的简单调试-System.out.println首先本次进行调试的一个程序是实现从1累加到100的功能&#xff0c;是在IDEA下进行编写的。如图所示&am…

1626_MIT 6.828 lab1课程大纲学习过程整理

全部学习汇总&#xff1a; GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 现在lab1的内容全都学习完了&#xff0c;该做的练习也都做了。接下来&#xff0c;整理一下自己看这一部分课程讲义的一些笔记。 整理之前&#xff0c;先把自己完成…

c# 跑马灯显示

//本文演示跑马灯//用到了线程、同步委托using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;using System.IO;nam…

鲜花数据集实验结果总结

从read_split_data中得到&#xff1a;训练数据集&#xff0c;验证数据集&#xff0c;训练标签&#xff0c;验证标签。的所有的具体详细路径 数据集位置&#xff1a;https://download.csdn.net/download/guoguozgw/87437634 import os #一种轻量级的数据交换格式&#xff0c; …

常见漏洞之 struts2+ jboss

数据来源 本文仅用于信息安全的学习&#xff0c;请遵守相关法律法规&#xff0c;严禁用于非法途径。若观众因此作出任何危害网络安全的行为&#xff0c;后果自负&#xff0c;与本人无关。 01 Struts2相关介绍 》Struts2概述 》Struts2历史漏洞&#xff08;1&#xff09; 》…

【Linux】Linux多线程(下)

前言 大家好呀,欢迎来到我的Linux学习笔记~ 本篇承上Linux多线程创建,线程互斥(互斥锁),线程同步(条件变量),继下接着学习线程同步的另一个信号量,以及后序的线程池&#xff0c;线程的懒汉单例模式和其他锁相关知识。&#xff08;注意本篇博客代码居多&#xff09; Linux多线程…