Java零基础后端知识(二)

简介: Java零基础后端知识

Map

Map

特点 key-value映射

HashMap

Key无序 唯一(Set)

value 无序 不唯一(Collection)

实现方式:数组+链表(jdk1.7的时候)

实现方式:数组+链表+红黑树(jdk1.8之后)

LinkedHashMap

有序的HashMap 速度快

实现方式:链表

TreeMap

有序 速度没有hash快

实现方式:红黑树

基本api操作:

增加:put(k,v)

查找:isEmpty()

清空集合中的所有元素:clear()


Map.entry:表示的是K-V组合的一组映射关系,key和value成组出现。

HashMap和HashTable的区别:


hashmap线程不安全,效率比较高,hashtable线程安全,效率低。

hashmap中key和value可以为空。hashtable键和值都不可以为空。

HashMap源码:每次快满还没满的时候要进行扩容操作。

很多数字是为了减少哈希碰撞。


hash初始值为2的N次幂:


方便进行&操作,提高效率,&要比取模运算效率要高。

hash&(initCapacity-1)

在扩容之后涉及到元素的迁移过程,迁移的时候只需要判断二进制的前一位是0或者是1即可。如果是0,表示新数组和旧数组的下标位置不变,如果是1,只需要将索引位置加上旧数组的长度值即为新数组的下标。

1.7源码知识点:

默认初始容量

加载因子

put操作

1.(设置值,计算hash)

2.扩容操作

3.数据迁移的过程

jdk1.8:当链表长度超过8时,链表会转换成红黑树,方便查找。


Collections及File类讲解


Collections工具类:

Collections和Collection不同,前者是集合的操作类,后者是集合接口。

Collections提供的静态方法:

addAll():批量添加 Collecctions.addAll();

sort():排序

binarySeach():二分查找

fill():替换 填充。把所有元素都填充成一个元素

shuffle():随机排序

reverse():逆序


Arrays:

Arrays提供了数据操作的工具类,包含很多方法:

集合和数组之间的转换 数组转成list

集合总结:


603b63553ec74a73aa518da628e54bf9.png


File:

File类提供了对当前文件系统中文件的部分操作。


创建文件 newFile()

判断文件的属性 canRead() ,都会返回boolean类型的值

判断当前文件是否存在 file.exists()

获取文件的名称file.getName()

获取文件的绝对路径

获取文件的父路径名称,如果文件的路径中只包含文件名称,则显示空。

无论当前文件是否存在,只要给定具体的路径,都可以返回相应的路径名称。

判断文件是否是文件或者目录

打印当前文件系统的所有盘符 File.listRoots()

创建单级目录 file.mkdir()

创建多级目录 file.mkdirs()

//循环遍历输出c盘中的所有文件的绝对路径。

//文件在遍历的时候,会出现空指针的问题,原因在于当前文件系统受保护,某些文件没有访问权限,此时会报空指针异常。


IO流


当写完程序时一定要注意关闭流。

步骤:


选择合适的io流对象

创建对象

传输数据

关闭流对象(会占用系统资源)

优化:添加缓冲区,而不是每次只读一个字节,缓冲区就用缓冲数组来表示,每次会将数据添加到缓冲区中,当缓冲区满了之后,一次读取。


字符流可以直接读取中文汉字,而字节流在处理的时候会出现中文乱码。


Java多线程

线程的概念


程序:是一个指令的集合

进程:是一个静态的概念(正在执行中的程序)作为资源分配的单位

进程时程序的一次静态执行过程,占用特定的地址空间。(占有一定的资源)

线程:是进程中一个“单一的连续控制流程”/执行路径。 线程又被称为轻量级进程。(调度执行的单位)

一个进程可以拥有多个并行的线程。


实现线程的方式


  1. 继承Thread类,调用start方法。


public class XianCheng extends Thread{
    @Override
    public void run() {
       for(int i=0;i<10;i++){
           System.out.println(i);
       }
    }
}

实现Runnable接口:(使用了代理模式)

虽然使用的thread类来执行,但是使用的却是runnable里面的东西。

不需要给共享变量添加static关键字,每次创建一个对象,作为共享对象即可

class Xiancheng2 implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<10;i++){
            System.out.println(i);
        }
    }
}

线程的代理设计模式:

举例:

潘金莲和西门庆勾结,但是不敢直接勾结,需要王婆作为代理。表面上是王婆联系的,但是是潘金莲在做事。

定义一个顶层的接口:(代理人和被代理人都有的行为)


public interface KindWomen {
    public void playWithMan();
    public void makeEyesWithMan();
}

潘金莲这个实体类,也是被代理人:

public class PanJinLian implements KindWomen{
    @Override
    public void playWithMan() {
        System.out.println("潘金莲。。。。");
    }
    @Override
    public void makeEyesWithMan() {
        System.out.println("潘金莲在和男人抛媚眼");
    }
}

王婆这个代理人(表面上是王婆在做事,实际上是被代理人在做事):

public class WangPo implements KindWomen{
    private KindWomen kindWomen;
    public WangPo(){//默认用潘金莲作为代理
        this.kindWomen=new PanJinLian();
    }
    public WangPo (KindWomen kindWomen){
        this.kindWomen=kindWomen;
    }
    @Override
    public void playWithMan() {
       this.kindWomen.playWithMan();//自己干不动了让别人去干
    }
    @Override
    public void makeEyesWithMan() {
       this.kindWomen.makeEyesWithMan();
    }
}

线程的生命周期


创建

就绪

(阻塞)

运行

终止

1.新生状态:

当创建好当前线程对象之后,没有启动之前(调用start方法之前)

ThreadDemo thread=new ThreadDemo()

RunnableDemo run=new RunnableDemo()

2.就绪状态:

准备开始执行,并没有执行,表示调用start方法之后

当对应的线程创建完成,且调用start方法之后,所有的线程会添加到一个就绪队列中,所有的线程同时去抢占cpu的资源。

3. 运行状态:

当当前进程获取到cpu资源之后,就绪队列中的所有线程会去抢占cpu的资源,谁先抢占到谁先执行,在执行的过程中就叫做运行状态。抢占到cpu资源,执行代码逻辑开始。

4. 死亡状态:

当运行中的线程正常执行完所有的代码逻辑或者因为异常情况导致程序结束叫做死亡状态。

进入的方式:

1.正常运行完成且结束

2.认为中断执行,比如使用stop方法

3.程序抛出未捕获的异常

5. 阻塞状态:

在程序运行过程中,发生某些异常情况,导致当前线程无法再顺利执行下去,此时会进入阻塞状态,进入阻塞状态的原因消除之后,所有的阻塞队列会再次进入到就绪状态中,随机抢占cpu的资源,等待执行。

进入的方式:sleep方法 等待io资源


介绍线程类api方法


public static void main(String[] args) {
       //获取当前线程对象
        Thread thread=Thread.currentThread();
        //获取当前线程的名称
        System.out.println(thread.getName());
        //获取线程的id
        System.out.println(thread.getId());
        //获取线程的优先级,在一般系统中范围是0-10的值,如果没有经过设置的话,就是默认值5,也可以自己设置。
        System.out.println(thread.getPriority());
        //设置线程池的优先级
        /**
         * 优先级越高一定越优先执行嘛?
         *   不一定,只是优先级越高执行的概率越大。
         */
        thread.setPriority(10);
        System.out.println(thread.getPriority());
    }

public final void join() 调用该方法强制执行

public static void sleep() 使正在执行的线程休眠millis秒

public static void yield() 当前正在执行的线程暂停一次,允许其他线程执行,不阻塞,线程进入就绪状态 ,当前线程就会马上恢复执行。

public final void stop() 强迫线程停止执行。已过时,不推荐使用。

注意:在多线程的时候,可以实现唤醒和等待的过程,但是唤醒和等待操作的对应不是thread类,而是我们设置的共享对象和共享变量。


阻塞状态:有三种方法可以暂停Thread执行:


sleep:不会释放锁,sleep时的线程也不可以访问锁定对象。

yield:让出CPU的使用权,从运行态直接进入就绪态。让CPU重新挑选哪一个线程进入运行状态。

join:当某个线程等待另一个线程执行结束后,才继续执行时,使调用该方法的线程在此之前执行完毕,也就是等待调用该方法的线程执行完毕后再往下继续执行。

多线程并发访问的时候会出现数据安全问题:

解决方式:

同步代码块

synchronized(共享资源,共享对象,需要的是object的子类)(具体执行的代码块)

2. 同步方法:

将核心的代码逻辑定义成一个方法,使用synchronized关键字进行修饰,


死锁


同步可以保证资源共享操作的正确性,但是过多同步也会产生死锁。

死锁一般情况下表示互相等待,是程序运行时出现的一种问题。


Java线程池


使用线程池管理线程主要有如下好处:

使用线程池可以重复利用已有的线程继续执行任务,避免线程在创建和销毁时造成的消耗

由于没有线程创建和销毁时的消耗,可以提高系统响应速度

通过线程可以对线程进行合理的管理,根据系统的承受能力可运行线程数量的大小等


线程池工作原理:


线程池执行所提交的任务过程:

先判断线程池中核心线程池所有的线程是否都在执行任务。如果不是,则新创建一个线程执行刚提交的任务,否则,核心线程池中所有的线程都在执行任务,则进入第2步。

判断当前阻塞队列是否已满,如果未满,则将提交的任务放置在阻塞队列中;否则,则进入第3步。

判断线程池中所有的线程是否都在执行任务,如果没有,则创建一个新的线程来执行任务,否则,则交给饱和策略进行处理


设计一个线程类:

public class Task implements  Runnable{

线程池的使用:

  • CacheThread:线程个数没有限制
public class CacheThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for(int i=0;i<20;i++){
            executorService.execute(new Task());//线程执行,进行了一个线程的复用
        }
       //线程关闭
        executorService.shutdown();
    }
}
  • FixedThread:线程是可以自己指定的
public class FixedThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(5);//最多只允许5个线程数量执行
        for(int i=0;i<20;i++){
            executorService.execute(new Task());
        }
        executorService.shutdown();
    }
}

newSingleThreadExectue:线程是单一的

public class SingleThreadPoolDemo {
    public static void main(String[] args) {
        //一个线程
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for(int i=0;i<20;i++){
            executorService.execute(new Task());
        }
        executorService.shutdown();
    }
}
相关文章
|
19天前
|
jenkins Java 测试技术
如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例详细说明
本文介绍了如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例,详细说明了从 Jenkins 安装配置到自动构建、测试和部署的全流程。文中还提供了一个 Jenkinsfile 示例,并分享了实践经验,强调了版本控制、自动化测试等关键点的重要性。
53 3
|
19天前
|
小程序 前端开发 算法
|
1月前
|
JSON 前端开发 Java
震惊!图文并茂——Java后端如何响应不同格式的数据给前端(带源码)
文章介绍了Java后端如何使用Spring Boot框架响应不同格式的数据给前端,包括返回静态页面、数据、HTML代码片段、JSON对象、设置状态码和响应的Header。
135 1
震惊!图文并茂——Java后端如何响应不同格式的数据给前端(带源码)
|
1月前
|
NoSQL 安全 Java
Java后端基础自测
Java后端基础自测
60 12
|
1月前
|
jenkins Java 测试技术
如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例详细说明
【10月更文挑战第8天】本文介绍了如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例,详细说明了从 Jenkins 安装配置到自动构建、测试和部署的全流程。文中还提供了一个 Jenkinsfile 示例,并分享了实践经验,强调了版本控制、自动化测试等关键点的重要性。
36 5
|
1月前
|
前端开发 小程序 Java
java基础:map遍历使用;java使用 Patten 和Matches 进行正则匹配;后端传到前端展示图片三种情况,并保存到手机
这篇文章介绍了Java中Map的遍历方法、使用Pattern和matches进行正则表达式匹配,以及后端向前端传输图片并保存到手机的三种情况。
20 1
|
1月前
|
算法 Java Linux
java制作海报五:java 后端整合 echarts 画出 折线图,项目放在linux上,echarts图上不显示中文,显示方框口口口
这篇文章介绍了如何在Java后端整合ECharts库来绘制折线图,并讨论了在Linux环境下ECharts图表中文显示问题。
39 1
|
1月前
|
算法 搜索推荐 Java
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
这篇文章介绍了如何使用Java后端技术,结合Graphics2D和Echarts等工具,生成包含个性化信息和图表的海报,并提供了详细的代码实现和GitHub项目链接。
107 0
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
|
1月前
|
存储 前端开发 Java
Java后端如何进行文件上传和下载 —— 本地版(文末配绝对能用的源码,超详细,超好用,一看就懂,博主在线解答) 文件如何预览和下载?(超简单教程)
本文详细介绍了在Java后端进行文件上传和下载的实现方法,包括文件上传保存到本地的完整流程、文件下载的代码实现,以及如何处理文件预览、下载大小限制和运行失败的问题,并提供了完整的代码示例。
484 1
|
1月前
|
JSON 安全 前端开发
第二次面试总结 - 宏汉科技 - Java后端开发
本文是作者对宏汉科技Java后端开发岗位的第二次面试总结,面试结果不理想,主要原因是Java基础知识掌握不牢固,文章详细列出了面试中被问到的技术问题及答案,包括字符串相关函数、抽象类与接口的区别、Java创建线程池的方式、回调函数、函数式接口、反射以及Java中的集合等。
29 0

热门文章

最新文章

下一篇
无影云桌面