加入收藏 | 设为首页 | 会员中心 | 我要投稿 拼字网 - 核心网 (https://www.hexinwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

线程池linux 延年有余的技术博客

发布时间:2022-11-07 12:49:48 所属栏目:Linux 来源:
导读:  简单三分钟自我介绍

  自我介绍这里一笔带过,给对面介绍自己内在 + 外在 + 校园经历 + 校园项目 + 意向岗位

  一面1. Java基础1.1 序列化和反序列化

  首先了解一下序列化和反序列化的概念
  简单三分钟自我介绍
 
  自我介绍这里一笔带过,给对面介绍自己内在 + 外在 + 校园经历 + 校园项目 + 意向岗位
 
  一面1. Java基础1.1 序列化和反序列化
 
  首先了解一下序列化和反序列化的概念
 
  序列化:将Java对象以二进制即字节码的形式保存在磁盘文件中,可以说是保存Java对象状态的过程,序列化可以实现对象保存的持久化;
 
  反序列化:将保存在磁盘文件中的Java字节码重新转换为Java对象的过程;
 
  其他特点:一般RPC框架底层协议通信就是通过序列化和反序列化在网络上传输Java对象。
 
  序列化和反序列化的实现主要有两种,准确来说有三种方法:
 
  采用默认的序列化方式,即通过ObjectOutPutStream类的writeObject(OutputStream out)方法来序列化到输出流中
 
  输出流可以选择文件流、也可以选择管道流,甚至是二进制流
 
  文件流是直接写到文件中再读取转成对象,管道流是通过管道缓存数据,然后再通过输入流连接管道读取转成对象
 
  序列化的对象必须实现Seriablized接口,才能完成序列化和反序列化操作
 
  class Student implements Serializable {
     private String name;
     private Integer age;
  }
  //FileOutputStream fos = new FileOutputStream("D:\\student.txt");
        PipedOutputStream pos = new PipedOutputStream();
        PipedInputStream pis = new PipedInputStream();
        pis.connect(pos);
        ObjectOutputStream oos = new ObjectOutputStream(pos);
        Student student = new Student();
        student.setAge(21);
        student.setName("zs");
        oos.writeObject(student);
        //FileInputStream fis = new FileInputStream("D:\\student.txt");
        ObjectInputStream ois = new ObjectInputStream(pis);
        Student res = (Student) ois.readObject();
        System.out.println(res);
  // 自定义协议 比如我可以将加入对象头 cafe babe
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        System.out.println("自定义反序列化");
        int magic = in.readInt();
        this.name = (String) in.readObject();
        this.age = (Integer) in.readObject();
     }
     // 自定义协议 比如我可以将加入对象头 cafe babe
     private void writeObject(ObjectOutputStream out) throws IOException {
        System.out.println("自定义序列化");
        // 4 字节 魔数
        out.writeInt(0xCAFEBABE);
        out.writeObject(this.name);
        out.writeObject(this.age);
     }
  实现接口Externalizable并重写方法,其实跟第二种差别不大,只是第二种有默认的私有方法
 
  @Override
     public void writeExternal(ObjectOutput out) throws IOException {
        System.out.println("实现 Externalizable 接口的自定义序列化");
        out.writeObject(this.name);
        out.writeObject(this.age);
     }
     @Override
     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        System.out.println("实现 Externalizable 接口的自定义反序列化");
        this.name = (String) in.readObject();
        this.age = (Integer) in.readObject();
     }
  解决反序列化破坏单例
 
  解决反射破坏单例
 
  反射创建对象根本也是要调用构造方法,而且可以无视构造方法的访问修饰符(public、private)
 
  1.2 说一说数据类型有哪些
 
  Java有八种基本数据类型 + String
 
  1个位的bit,布尔类型的boolean,2个字节的short,4个字节的int、char,8个字节的long、double、float
 
  其中基本类型中的包装类型常用的有Integer、Long
 
  其中Integer会自动进行拆封装处理,也就是可以直接跟int类型比较数值上的大小
 
  底层在-128-127之间会做缓存,在这之间通过Integer.valueOf(int)创建的对象都是同一个,使用了享元设计模式
 
  System.out.println(new Integer(1) == 1);
  System.out.println(Integer.valueOf(1) == Integer.valueOf(1));
  System.out.println(Integer.valueOf(128) == Integer.valueOf(128));
  结果
 
  true
  true
  false
  1.3 数据结构
 
  给你你个浏览器,要求设计前进和后退的数据结构,优先考虑性能
 
  那么由于浏览器前进后退访问,是一种FIFO的结构,比如你连续点击前进几个页面,最先进的页面最后返回,即LIFO
 
  那么可以考虑栈的结构设计,栈结构设计要考虑性能,首先我们可以分析到,浏览器页面跳转没有涉及到页面的修改,即用于查询
 
  那么优先考虑数组而不考虑链表
 
  我们可以设计两个栈数组,一个用于入栈已前进的页面,一个用于入栈已后退的页面,取其中一个栈顶元素作为当前页面
 
  2. MySQL2.1 索引
 
  在MySQL中,直接影响索引类型的是数据库的存储引擎
 
  使用MyIsam存储引擎,数据文件和索引是分开的,索引会另外存储在另一个文件中
 
  使用InnoDB存储引擎,数据和索引都存储在同一个文件中,而且是以B+数的数据结构存储,非叶子节点存储索引,叶子节点存储索引和索引对应的数据
 
  就MyIsam引擎来说,索引中最主要的是聚簇索引,也就是主键的默认索引
 
  单值索引和多值索引,这里是指组合索引,好的组合索引可以达到覆盖索引,可以做到避免回表,这里是因为叶子节点通过覆盖索引带了数据,因为B+树只有叶子节点带有数据,非叶子节点都是索引
 
  而多个组合索引下,有效索引要做到左匹配,也就是必须从左顺序匹配到右查询,否则索引将失效
 
  2.2 口述 sql
 
  给你一张表,有三个字段,id、产品id、备注信息,现在需要你查询相同产品id的记录,然后id值相同的记录数大于等于5的产品id
 
  首先呢,我们可以先定义这张表为S
 
  因为涉及相同字段的记录,可以考虑直接分组,使用聚合函数
 
  select pro_id from S
  group by pro_id
  having count(pro_id) >= 5
  3. JVM3.1 线程的死锁了解过吗?
 
  比如有两个线程t1和t2,t1线程有资源r1,t2有资源r2,t1线程执行代码中需要资源r2,不过这段代码需要t2线程把资源r2释放才能执行,此时t2线程也执行代码中,释放资源前需要获取资源r1,但t2又需要r2,此时处于相互等待的状态,就导致了死锁。
 
  从Java角度来说,资源相当于Java的锁对象,是互斥的,一个线程获取锁对象后,另一个线程只能等待,t1线程获取锁对象r1,也就是占有了锁r1,这时线程t2也是占有了锁对象r2,而线程t1需要获取锁对象r2才能往下执行代码,使得线程t1阻塞,而线程t2处于阻塞等待锁对象r1释放,才能释放锁对象r2,这样就导致死锁。(互相等待)
 
  4. JUC4.1 线程池有了解过吗?
 
  线程池主要有核心线程数、救急线程和队列,队列分为阻塞队列和非阻塞队列。
 
  目前线程池主要可以分为几类:
 
  只有核心线程、无救急线程的线程池,此时等待队列中有要执行的任务,而核心线程在轮询地执行等待队列中的任务,如果队列满或者队列是无界队列,可能导致内存溢出问题。
 
  一般这种线程池的做法就是使用了拒绝策略,拒绝策略可分为直接丢弃新任务、异常抛出(主动逻辑处理)、丢弃等待队列头结点、提交任务线程执行。
 
  最后一个是推荐使用的
 
  只有救急线程的线程池,这种的话有线程池newCachedThreadPool,它能无限创建救急线程,队列采用SynchronousQueue ,是一个没有容量的队列,只有线程取任务时才能提交任务;
 
  最后是一种核心线程数只有1的线程池,没有救急线程,任务队列无界,一般作为单线程任务,这样就不会有CPU的轮询切换,任务的执行效率最高,不过请求数太多的情况下,也是容易导致内存溢出。
 
  非阻塞队列实现的有CurrentLinkedQueue,它是通过CAS无锁化机制的线程池队列,每个线程通过for(;;)执行,是一个单向且通过GC自动回收出队节点的,利用可达性算法分析,将next指向自己线程池linux,即可触发延迟回收,利用元素的不可重用性,规避ABA问题
 
  5. Linux
 
  给你一个日志文件,要求你查询最近一天内中,匹配到关键字的所有记录数据
 
  一般日志实时查询可以使用该命令,它会实时更新,而且会处于fg模式,tail打印文件末尾记录,也就是最近
 
  tail -100f catalina.log | grep "关键字"
  而使用cat是查询历史,只能打印日志到屏幕
 
  比如按照tail或head来查询关键字为20:的后5条数据并显示行号
 
  cat -n log.log4j | grep "20:" | tail -n 5
  时间段查询
 
  grep '2022-08-21 20:1[1-9]' log.log4j
  综合使用
 
  cat -n log.log4j | grep -E "关键字|2022-08-21 20:1[0-9]" | tail -n 10
 

(编辑:拼字网 - 核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!