• 文章
  • 在线工具
  • 热门 java如何实现栈数据结构

     2021-08-18 16:17  69    
    package com.nanxhs.structure;import java.lang.reflect.Array;/** * 栈实现 * @author 唐海斌 * @version 1.0 * @date 2021/5/19 11:17 */public class Stack<T> { /** * 初始化大小 */ private static final int INIT_ARRAY_SIZE = 10; /** * 栈游标指针,指示当前最新数据的下标 */ private int point = -1; /** * 栈中元素的类型 */ private Class<T> clazz; /** * 元素容器 */ private T[] stack; public Stack(Class<T> clazz) { stack = (T[]) Array.newInstance(clazz, INIT_ARRAY_SIZE); this.clazz = clazz; } /** * 入栈 * @param element */ public void push(T element) { if (element == null) { throw new RuntimeException("element not null"); } if (++point == length() - 1) { dilatation(); } stack[point] = element; } /** * 出栈 * @return */ public T pop() { if (point < 0) { return null; } return stack[point--]; } /** * 清空栈 */ public void clear() { while (point > -1) { pop(); } } /** * 栈的当前容量 * @return */ public int length() { return stack.length; } /** * 栈元素数量 * @return */ public int count() { return point + 1; } /** * 动态扩容 */ private void dilatation() { T[] newStack = (T[]) Array.newInstance(clazz, length() * 2); for (int index = 0; index < stack.length; ++index) { newStack[index] = stack[index]; } stack = newStack; }}测试类import com.nanxhs.structure.Stack;import org.junit.Assert;import org.junit.Test;/** * @author 唐海斌 * @version 1.0 * @date 2021/5/19 11:36 */public class StackTest { @Test public void test() { Stack<String> stack = new Stack<>(String.class); stack.push("+"); stack.push("-"); stack.push("*"); stack.push("/"); Assert.assertEquals(4, stack.count()); Assert.assertEquals(stack.pop(), "/"); stack.clear(); Assert.assertNull(stack.pop()); }}
  • 热门 java实现单向链表数据结构代码

     2021-08-18 13:17  77    
    package com.nanxhs.structure;import java.util.Objects;/** * * 单向链表实现 * @author 唐海斌 * @version 1.0 * @date 2021/5/20 11:16 */public class UnidirectionalLinkList<T> { /** * 表头, 只是标识作用,一个空元素的Node */ private final Node head; /** * 表尾 */ private Node tail; /** * 链表长度 */ private int size; public UnidirectionalLinkList() { head = new Node(null); } /** * 加入表尾 * @param element */ public synchronized void add(T element) { Node node = new Node(element); if (tail == null) { head.next = node; tail = node; } else { Node oldTail = tail; tail = node; oldTail.next = node; } ++size; } /** * 加入表头 * @param element */ public synchronized void addFirst(T element) { Node firstNode = head.next; Node node = new Node(element); if (firstNode == null) { head.next = node; tail = node; } else { head.next = node; node.next = firstNode; } ++size; } /** * 从链表中移除 * @param element */ public synchronized boolean remove(T element) { Node node = head; Node prev; Node currNode; boolean status = false; while (node != null) { prev = node; currNode = node.next; if (currNode == null) { break; } if (Objects.equals(element, currNode.element)) { if (currNode.next == null) { prev.next = null; currNode.element = null; }else { prev.next = currNode.next; } --size; node = prev.next; status = true; } else { node = currNode; } } return status; } /** * 删除指定下标的元素 * @param index * @return */ public synchronized boolean remove(int index) { if (index > size - 1) { throw new RuntimeException("超过链表长度,当前链表的长度为: " + size); } Node node = head; int i = 0; while (node != null) { Node currentNode = node.next; if (currentNode == null) { return false; } if (Objects.equals(i, index)) { node.next = currentNode.next; if (--size == 0) { tail = null; } return true; } node = currentNode; ++i; } return false; } /** * 获取指定下标的元素 * @param index * @return */ public T get(int index) { if (index > size - 1) { throw new RuntimeException("超过链表长度,当前链表的长度为: " + size); } Node node = head; int i = 0; while (node != null) { Node currentNode = node.next; if (currentNode == null) { return null; } if (Objects.equals(i, index)) { return currentNode.element; } node = currentNode; ++i; } return null; } /** * 清空链表 */ public void clear() { for (int index = size; index > 0; --index) { remove(0); } } /** * 获取链表长度 * * @return */ public int getSize() { return size; } @Override public String toString() { StringBuilder dataStr = new StringBuilder(); dataStr.append("["); Node node = head; while ((node = node.next) != null) { dataStr.append(node.element).append(", "); } return dataStr.append("]").toString(); } class Node { /** * 下一个节点 */ private Node next; /** * 当前节点元素 */ private T element; public Node(T element) { this.element = element; } }}测试类import com.nanxhs.structure.UnidirectionalLinkList;import org.junit.Assert;import org.junit.Test;/** * @author 唐海斌 * @version 1.0 * @date 2021/5/20 13:35 */public class UnidirectionalLinkListTest { @Test public void test() { UnidirectionalLinkList<String> unidirectionalLinkList = new UnidirectionalLinkList<>(); unidirectionalLinkList.add("小明"); unidirectionalLinkList.add("张三"); Assert.assertEquals("张三", unidirectionalLinkList.get(1)); unidirectionalLinkList.addFirst("李四"); Assert.assertEquals("李四", unidirectionalLinkList.get(0)); unidirectionalLinkList.remove("张三"); Assert.assertEquals("小明", unidirectionalLinkList.get(1)); unidirectionalLinkList.remove(1); Assert.assertEquals("李四", unidirectionalLinkList.get(0)); unidirectionalLinkList.clear(); Assert.assertEquals(unidirectionalLinkList.getSize(), 0); }}
  • 最新 热门 JWT使用介绍以及工具类

     2021-04-30 11:14  6221    
    一、JWT是什么1.基本介绍JSON Web Token(JWT)是一个非常轻巧的规范。JSON网络令牌,JWT是一个轻便的安全跨平台传输格式,定义了一个紧凑的自包含的方式在不同实体之间安全传输信息(JSON格式)2.应用场景允许我们在用户和服务器之间传递安全可靠的加密字符串信息进行认证和授权校验。二、原理1.JWT的构成加密的字符串由三部分组成:头部+载体+签名①.头部(Header)头部用于描述关于该JWT的最基本信息,例如其他类型以及签名所用的算法等。可以被表示成一个json对象。{"typ":"JWT","alg":"HS256"}②.载荷(Payload)载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三部分1)、以下是标准中注册的声明,建议但不强制使用iss:jwt签发者sub:当前令牌描述的说明aud:接收jwt的一方exp:jwt的过期时间,这个过期时间必须要大于签发时间nbg:定义在什么时间之前,该jwt都是不可用的iat:jwt的签发时间jti:jwt的唯一身份表示,主要用啦作为一次性token,从而回避攻击2)、公共的声明(不参与校验)公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息,但不建议添加敏感信息,因为该部分是可以被解密。3)、私有的声明(不参与校验)私有声明是提供者和消费者所共同定义的声明,一般不建议存放铭感信息,Base64是对称解密的。4)定义一个payload:{"sub":"这里是载体内容","name":"JEEM","admin":"true"}③.签证(signature)jwt的第三部分是一个签证信息(校验数据是否正确),这个签证信息由三部分组成header(base64后的)payload(base64后的)secret(秘钥)这个部分需要base64加密后的header和base64加密后的payload。链接组成的字符串,然后通过header声明的加密方式加盐secret组合加密,然后就构成了jwt的三部分。eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. //头部eyJpc3MiOiLlvKDlvLoiLCJuYW1lIjoiNzg5IiwiZXhwIjoxNTI4MzY0MjU5LCJpYXQiOjE1MjgzNjMwNTl9.//载荷574koY-c9SqMNNzfvAWQuKEnimWeZAcoFQ5XudNWF3o //签名注意:secret是秘钥保存在服务端,一定不能泄露。三、如何使用1、引入POM<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version></dependency>2、代码使用import com.auth0.jwt.JWT;import com.auth0.jwt.JWTVerifier;import com.auth0.jwt.algorithms.Algorithm;import com.auth0.jwt.interfaces.DecodedJWT;public class TokenUtil { //默认过期时间设置(7) private static final long expireTime = 1000*60*60*24*7; public static String getToken(Object tokenVo, String tokenSecret){ return build(tokenVo, tokenSecret,expireTime); } public static String getToken(Object tokenVo, String tokenSecret, long expireTime){ return build(tokenVo, tokenSecret,expireTime); } private static String build(Object tokenVo, String tokenSecret, long expireTime){ //过期时间和加密算法设置 Date date=new Date(System.currentTimeMillis()+expireTime); Algorithm algorithm = Algorithm.HMAC256(tokenSecret); //头部信息 Map<String,Object> header=new HashMap<>(2); header.put("typ","JWT"); header.put("alg","HS256"); Map map = new HashMap(); try { map = BeanUtils.describe(tokenVo); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return JWT.create() .withHeader(header) .withClaim("data", map) //自定义载荷 .withExpiresAt(date) //过期时间.sign(algorithm); //加盐 }/** * 解析token */ public static <T> T getTokenData(String token, Class<T> clazz){ DecodedJWT jwt = JWT.decode(token); try { Map map = jwt.getClaim("data").asMap(); T vo = clazz.newInstance(); BeanUtils.populate(vo,map); return vo; } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } /** * 获取解析后的JWT */ public static DecodedJWT getDecodedJWT(String token){ return JWT.decode(token); } /** * 验证token * @param token */ public static boolean verifyToken(String token, String tokenSecret){ JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(tokenSecret)).build(); jwtVerifier.verify(token); return true; } public static void main(String[] args){ System.out.println(TokenUtil.getToken(new UserTokenVo(),"123456")); }}
  • 最新 热门 Nginx高迸发访问限流处理方式

     2021-04-26 06:14  9439    
    应用场景:一般情况下,并发量是比较大的数据接口,并且不经常变动的数据,需要做多级缓存,另外没有做缓存的数据接口,用户不断刷新,访问频率过快,有恶意的大量请求爬取数据,会对系统造成影响。而限流就是保护措施之一。限流(迸发访问次数)限制单个ip访问次数 (恶意攻击爬取)队列均速放行(缓冲队列)1.Nginx限流说明: 使用nginx的 ngx_http_limit_req_module模块进行限制的,使用limit_req和limit_req_zone命令来设置;1)http模块下添加:#1.每秒允许10次访问,10M的缓存空间limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=10r/s;#2.根据某个ip来限制,存储空间大小为1m#limit_req_zone $binary_remote_addr zone=addr:1m$binary_remote_addr:根据请求IP地址进行限流key:定义限流对象, binary_remote_addr,是基于 remote_addr(客户端IP) 来做限流,binary_ 开头的目的是压缩内存占用量zone: 定义共享内存区来存储访问信息, ip_limit:10m表示一个大小为10M,名字为ip_limit的内存区域。1M能存储16000 IP地址的访问信息,10M可以存储16W IP地址访问信息rate: 用于设置最大访问速率,rate=10r/s 表示每秒最多处理10个请求。Nginx 实际上以毫秒为粒度来跟踪请求信息,因此 10r/s 实际上是限制:每100毫秒处理两个请求。这意味着,自上一个请求处理完后,若后续100毫秒内又有请求到达,将拒绝处理该请求。2)location模块下添加limit_req zone=ip_limit burst=15 nodelay;#对应上面的1limit_conn addr 5; #对应上面的2说明:zone=ip_limit对应上面的限流对象地址;bursrt=15表示最大支持15的并发,会有5个请求存在队列中,不会被拒绝;如果不加,则会被拒绝nodelay: 表示并发超出的5个请求,不会被延迟,会被立即执行,如需等待执行的话,配置delay即可。
  • 推荐 热门 CentOS8安装Docker报错package docker-ce-3:19.03.8-3.el7.x86_64 requires containerd.io >= 1.2.2-3

     2020-11-22 49:14  140828  42  
    1、问题描述: CentOS8安装Docker报错package docker-ce-3:19.03.8-3.el7.x86_64 requires containerd.io >= 1.2.2-32、错误展示:[root@iZbp1d8bd3d50zlx7kccj2Z /]# yum -y install docker-ceLast metadata expiration check: 0:09:43 ago on Sun 22 Nov 2020 01:55:52 PM CST.Error: Problem: package docker-ce-3:19.03.13-3.el7.x86_64 requires containerd.io >= 1.2.2-3, but none of the providers can be installed - cannot install the best candidate for the job - package containerd.io-1.2.10-3.2.el7.x86_64 is filtered out by modular filtering - package containerd.io-1.2.13-3.1.el7.x86_64 is filtered out by modular filtering - package containerd.io-1.2.13-3.2.el7.x86_64 is filtered out by modular filtering - package containerd.io-1.2.2-3.3.el7.x86_64 is filtered out by modular filtering - package containerd.io-1.2.2-3.el7.x86_64 is filtered out by modular filtering - package containerd.io-1.2.4-3.1.el7.x86_64 is filtered out by modular filtering - package containerd.io-1.2.5-3.1.el7.x86_64 is filtered out by modular filtering - package containerd.io-1.2.6-3.3.el7.x86_64 is filtered out by modular filtering - package containerd.io-1.3.7-3.1.el7.x86_64 is filtered out by modular filtering(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)3、解决问题: 由于centos8默认使用podman代替docker,所以需要安装一下containerd.io。 安装前请先执行下面一句 yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/containerd.io-1.2.6-3.3.fc30.x86_64.rpm接着继续安装。
  • 热门 Centos8 Docker CE 安装

     2020-11-22 25:14  131588  5  
    Centos Docker CE 安装Docker有两个分支版本:Docker CE和Docker EE,即社区版和企业版。本教程基于CentOS 安装Docker CE。1、安装Docker的依赖库。yum install -y yum-utils device-mapper-persistent-data lvm22、 添加Docker CE的软件源信息。yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo3、安装Docker CE。需要注意,如果是Centos8的话,需要先执行以下一句,否则会报错,centos8默认使用podman代替docker,所以需要安装containerd.io yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/containerd.io-1.2.6-3.3.fc30.x86_64.rpmyum makecache fastyum -y install docker-ce4、启动Docker服务。systemctl start docker
  • 推荐 热门 linux完整简洁笔记

     2020-09-10 07:11  121933  71  
    文件操作一、 文件类型(常见三种)文件表达方式: -目录(类似windows的文件夹)表达方式:d链接(类似windows的快捷方式)表达方式:l二、 文件权限r 可读w 可写x 可执行(脚本,比如shell脚本)- 特殊字符,表示没有任何权限文件的归属拥有者 owner u属于组 group g其他人 other o举例说明[root@iZm5e9tuuj84fiyy7b3bx3Z /]# lldrwxr-xr-x 3 root root 4096 Jun 23 09:04 applrwxrwxrwx 1 root root 7 Apr 26 15:48 bin-rw-r--r-- 1 root root 0 Jul 24 16:10 springboot.log1. 第一部分 drwxr-xr-x10个字符代表着不同意义,将这个10个字符分为4组,第一字符为1组,后面9个字符分3组 d rwx r-x r-x。第一字符表示文件类型后面9个字符表示针对不同用户的的权限关系d //第一个字符是文件类型,d代表着目录rwx //拥有者r-x //属于组r-x //其他人2. 第二部分 root root第一个字符串表示文件拥有者root第二个字符串表示文件所属组root修改权限*需要使用Root用户chmod 命令(change mode)举例说明:对于同组用户,仅仅可读; # chmod g-w 文件名称对于其他用户,既不可读也不可写 # chmod o-r 文件名称改变所属组和拥有者改变拥有者 # chown root /home/a.txt改变所属组 # chgrp root /home/a.txt三、文件查看cat 文件名称查看全部内容,适合内容比较少的方式 # cat a.txt more 文件名翻页查看内容,适合内容比较大的方式 # more a.txttail -f 文件名查看文件末尾的内容,一般查看日志用 # tail -f a.txt # tail -200f a.txt //200行head 文件名称查看文件开头内容,内容模板样式 # head a.txt四、文件创建touch 文件名称 # touch a.txt五、文件修改vim/vi 文件名称vi编辑器是所有Unix及Linux系统下标准的编辑器,他就相当于windows系统中的记事本一样,vim 具有程序编辑的能力,可以以字体颜色辨别语法的正确性,方便程序设计 # vim a.txtecho '内容' >> 文件名称文本内容追加 # echo '123456' >> a.txt快捷键(在vi查看模式下)* dd : 表示删除光标所在的行的内容* ZZ : 表示的是保存文件内容* x : 表示将光标处的字符给删除* o : 表示在光标的下一行进行插入内容六、文件的拷贝cp 文件名称 目标目录/名称复制单个文件或文件夹情况下(出现多个文件时报错) # cp a.txt /home/a.txtcp -r 目录 目标目录-r表示递归删除子文件复制目录及目录文件 # cp -r /etc/a.txt /home七、文件移动与重命名mv 文件 目标文件 同目录情况下则是重命名,不同目录则是移动 # mv a.txt b.txt # mv a.txt /home/b.txt八、文件删除rm 单个文件如果删除多个文件则会报错 # rm a.txt # rm filerm -rf filer表示递归删除子文件, f表示强制删除, 一般建议给绝对路径,以免误操作 # rm 九、创建目录mkdir 目录名称只能创建单个目录 # mkdir filemkdir -p 多级目录-p如果父级文件没有则创建,有则不创建 # mkdir -p /a/b/c十、链接软链接 sort link硬链接 hard link区别:删除连接时,是否删除源文件创建软链接 -s代表软连接 # ln -s file/dir linkName创建硬链接 # ln file/dir linkName十一、文件搜索find ~/ -name file~/当前目录,精确搜索 # find ~/ -name a.txtfind ~/ -name file*模糊搜索a开头的文件 # find ~/ -name a*系统管理一、查看系统信息uname[root@izwz9awjm6q5koj7sjg0jsz ~]# unameLinuxuname -r 查看版本[root@izwz9awjm6q5koj7sjg0jsz ~]# uname -r3.10.0-514.26.2.el7.x86_64cat /proc/cpuinfo 查看cpu信息[root@izwz9awjm6q5koj7sjg0jsz ~]# cat /proc/cpuinfoprocessor: 0vendor_id: GenuineIntelcpu family: 6model: 79model name: Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHzstepping: 1microcode: 0x1cpu MHz: 2494.224cache size: 40960 KB...date 查看当前日期cal 2020 查看日历表cat /proc/meminfo 查看内存信息[root@izwz9awjm6q5koj7sjg0jsz ~]# cat /proc/meminfoMemTotal: 1883724 kBMemFree: 118348 kBMemAvailable: 794852 kBBuffers: 77276 kBCached: 709520 kBSwapCached: 0 kBActive: 1339492 kB...df -lh 查看磁盘使用情况[root@izwz9awjm6q5koj7sjg0jsz ~]# df -lhFilesystem Size Used Avail Use% Mounted on/dev/vda1 40G 6.3G 31G 17% /devtmpfs 911M 0 911M 0% /devtmpfs 920M 0 920M 0% /dev/shmtmpfs 920M 508K 920M 1% /runtmpfs 920M 0 920M 0% /sys/fs/cgroupoverlay 40G 6.3G 31G 17% /var/lib/docker/overlay2/784d21c5380dd6edcc5943998078143/merged...du -sh 目录: 查看某个目录磁盘使用情况[root@izwz9awjm6q5koj7sjg0jsz home]# du -sh /home974M/homemount 查看挂在磁盘信息umount 卸载磁盘fdisk -l 修复磁盘,自动修复[root@izwz9awjm6q5koj7sjg0jsz home]# fdisk /homefree -m 看内存使用情况[root@izwz9awjm6q5koj7sjg0jsz ~]# free -m total used free shared buff/cache availableMem: 1839 900 119 0 819 769Swap: 0 0 0sudo设置普通用户权限vi /etc/sudoers//增加到第一行root2 ALL=(root)NOPASSWD:ALL防火墙sudo service iptables status 查看防火墙的状态sudo service iptables stop 停止关闭防火墙sudo service iptables start 启动防火墙sudo service iptables restart 重启防火墙sudo chkconfig iptables off|on 永久关闭|开启防火墙定时调度Crontabcrontab -e 创建定时任务 # crontab -e */1**** /bin/date >> /home/log.txtcrontab -l 查出任务列表crontabl -r 删除所有的任务软件安装1、第一种方式rpm -qa|grep name 检测软件是否安装[root@izwz9awjm6q5koj7sjg0jsz ~]# rpm -qa|grep javarpm -e --nodeps xxxxx 卸载已安装的软件rpm -ivh xxxx.rpm 安装软件2、第二种方式yum3、第三种方式tar 源码 编译 不推荐使用源码编译方式安装软件压缩软件zip压缩软件unzip xxx.zip 解压zip yy.zipe filename 压缩tar压缩软件tar zxvf xxxx.tar.gz 解压tar zcvf xxxx.tar.gz dir/file 压缩shell 编程注意事项编写脚本第一行指定用哪个程序来编译和执行脚本 #!/bin/bash 或者 #!/bin/sh变量名:必须以字母或下划线开头,后面可以跟字母、数字或者下划线。区分大小写敏感 # name=nihao //定义变量 # echo $name 或者 echo ${name} //打印变量 nihao # unset name //清除变量变量类型:根据变量的作用域,变量可以分为本地变量和环境变量;本地变量则是只在创建他们的shell中可用。而环境变量则在Shell中所有的用户进程都可以用,通常称为全局变量位置参量:是一种特殊的内置变量,通常被shell脚本用来从命令行接收参数,或者被函数用来保存传递给他的参数说明$0当前脚本文件名$1-9第 1 个到第 9 个位置参量${10}第 10 个位置参量$#位置参量个数$*以单个字符串显示所有位置参量$@未加双引号时与 $* 含义相同,加双引号时有区别$$脚本运行的当前进程号$!最后一个后台运行的进程的进程号$?显示前面最后一个命令的退出状态。О表示没有错误,其他任何值表示有错误。执行shell脚本时,用户可以通过命令行向脚本传递信息,跟在脚本名后面 以空格隔开每个字符串都称为位置参量例如:$1表示一个参数;$2表示第二个参数;第10个之后参数则用${10} //脚本内容 #!/bin/sh echo "hello ${1} ${2}" # . a.sh word! aaaaa hello word! aaaaa //打印语句执行脚本 # ./a.sh # . a.sh # sh a.shif判断命令关于某个档名的『文件类型』判断,如test -e filename表示存在否-e该『档名』是否存在?(常用)-f该『档名』是否存在且为档案(file)?(常用)-d该『文件名』是否存在且为目录(directory)?(常用)关于档案的权限侦测,如test -r filename表示可读否(但root权限常有例外)-r侦测该档名是否存在且具有『可读』的权限?-w侦测该档名是否存在且具有『可写』的权限?-x侦测该档名是否存在且具有『可执行』的权限﹖关于两个整数之间的判定,例如test ni -eq n2-eq两数值相等(equal)-ne两数值不等(not equal)-gtn1大于n2 (greater than)-ltn1小于n2 (less than)-gen1大于等于n2 (greater than or equal)-len1小于等于n2 (less than or equal)判定字符串的数据test -z string判定字符串是否为О?若string为空字符串,则为 truetest -n string判定字符串是否非为О?若string为空字符串,则为false.test str1 = str2str2判定str1是否等于str2 ,若相等,则回传 truetest str1 != str2判定str1是否不等于str2,若相等,则回传false1、单层、简单条件判断式if[条件判断式];then 当条件判断式成立时,可以进行的指令工作;fi // 将if反过来写,就成为fi啦!结束if之意!2、多重、复杂条件判断式if[条件判断式];then 当条件判断式成立时,可以进行的指令工作;elif[条件判断式];then 当条件判断式不成立时,可以进行的指令工作;else 当条件判断式不成立时,可以进行的指令工作;fi 循环 for var in 1 2 3 4 5 do echo ${var} done num=10 s=0 for((i=0;i<${num};i=i+1)) do s=$((${s}+${i})) done
  • 推荐 热门 非常好用的在线图片照片压缩工具

     2020-08-09 10:10  131271  85  
    在线使用: 在线压缩图片一款比较简单实用的图片压缩工具,根据自定义大小调整,像素调整图片,压缩后自动下载,支持GIF压缩、PNG压缩、JPG压缩不止有压缩图片工具这里还有很多其他的在线工具 :更多的在线工具
  • 推荐 热门 超简洁Json在线解析校验工具

     2020-08-08 53:18  128697  14  
    在线演示JSON校验:去演示源码下载:去下载JSON在线工具提供在线JSON解析,验证JSON格式,并提示错误问题位置,按JSON层级展现,可以收缩目录。是一款不错json转换验证的工具,不止JSON这里还有很多其他的在线工具: 更多的在线工具
  • 推荐 热门 易懂JavaNIO非阻塞流介绍

     2020-08-07 02:18  124112  32  
    Java NIO(New IO)简介从Java1.4版本开始引入的一个新的IO API与原来的IO有同样的作用和目的,使用的方式不同。NIO支持面向缓冲区、基于通道的IO操作。NIO将以更加高效的方式进行文件读写操作。传统的 IO 流都是阻塞式的。也就是说,当一个线程调用 read() 或 write()时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务。因此,在完成网络通信进行 IO 操作时,由于线程会阻塞,所以服务器端必须为每个客户端都提供一个独立的线程进行处理,当服务器端需要处理大量客户端时,性能急剧下降Java NIO 是非阻塞模式的。当线程从某通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。线程通常将非阻塞 IO 的空闲时间用于在其他通道上执行 IO 操作,所以单独的线程可以管理多个输入和输出通道。因此,NIO 可以让服务器端使用一个或有限几个线程来同时处理连接到服务器端的所有客户端。NIO和IO的区别IONIO面向流面向缓冲区阻塞IO非阻塞IO(无)选择器缓冲区(Buffer)简介在JavaNIO中负责存取数据,缓冲区就是数组。用于存储不同的数据类型(除了boolean类型),提供了对应的类型的缓冲区。ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer缓冲区的核心属性: capacity:容量,表示缓冲区大小,一旦声明不能改变 limit:界限,表示缓冲区可操作做的数据大小,limit 后面不能进行读写 position:位置,表示缓冲区中正在操作数据的位置。 mark:标记,用于需要记录position的位置。2. 缓冲区的核心方法: ByteBuffer.allocate(int):设置缓冲区大小 put():存数据到缓冲区 get():读取缓冲区数据 flip():切换到读取模式 rewind():可重复读数据,回到最开始读取 clear():回到最开始状态(但是数据不会被清理,处于被遗忘状态,基本属性还原) mark():标记当前的position位置。相当于备份3. 直接缓冲区与非直接缓冲区: a.字节缓冲区要么是直接的,要么是非直接的。如果为直接字节缓冲区,则 Java 虚拟机会尽最大努力直接在机 此缓冲区上执行本机 I/O 操作。也就是说,在每次调用基础操作系统的一个本机 I/O 操作之前(或之后),虚拟机都会尽量避免将缓冲区的内容复制到中间缓冲区中(或从中间缓冲区中复制内容)。 b.直接字节缓冲区可以通过调用此类的 allocateDirect() 工厂方法 来创建。此方法返回的 缓冲区进行分配和取消分配所需成本通常高于非直接缓冲区 。直接缓冲区的内容可以驻留在常规的垃圾回收堆之外,因此,它们对应用程序的内存需求量造成的影响可能并不明显。所以,建议将直接缓冲区主要分配给那些易受基础系统的机 本机 I/O 操作影响的大型、持久的缓冲区。一般情况下,最好仅在直接缓冲区能在程序性能方面带来明显好处时分配它们。 c.直接字节缓冲区还可以过 通过FileChannel 的 map() 方法 将文件区域直接映射到内存中来创建 。该方法返回MappedByteBuffer 。Java 平台的实现有助于通过 JNI 从本机代码创建直接字节缓冲区。如果以上这些缓冲区中的某个缓冲区实例指的是不可访问的内存区域,则试图访问该区域不会更改该缓冲区的内容,并且将会在访问期间或稍后的某个时间导致抛出不确定的异常 d.字节缓冲区是直接缓冲区还是非直接缓冲区可通过调用其 isDirect() 方法来确定。提供此方法是为了能够在性能关键型代码中执行显式缓冲区管理 。缓冲区Buffer代码使用String str = "abcdef";ByteBuffer b = ByteBuffer.allocate(1024);System.out.println(b.isDirect());b.put(str.getBytes());System.out.println("------------------");System.out.println("capacity: "+b.capacity());System.out.println("limit: "+b.limit());System.out.println("position: "+b.position());System.out.println("---------flip---------");b.flip();//切换读取,否则读取不出System.out.println("capacity: "+b.capacity());System.out.println("limit: "+b.limit());System.out.println("position: "+b.position());System.out.println("---------get---------");byte[] byt = new byte[b.limit()];b.get(byt);//获取System.out.println(""+new String(byt));System.out.println("capacity: "+b.capacity());System.out.println("limit: "+b.limit());System.out.println("position: "+b.position());System.out.println("---------rewind---------");b.rewind();//重读System.out.println("capacity: "+b.capacity());System.out.println("limit: "+b.limit());System.out.println("position: "+b.position());System.out.println("---------clear---------");b.clear();//回到原始状态,但并没有清空数据,数据处于被遗忘状态System.out.println("capacity: "+b.capacity());System.out.println("limit: "+b.limit());System.out.println("position: "+b.position());直接缓冲区(内存映射文件方式)代码使用FileChannel reader = FileChannel.open(Paths.get("D:/c.jpg"), StandardOpenOption.READ);FileChannel writer = FileChannel.open(Paths.get("D:/c3.jpg"), StandardOpenOption.WRITE,StandardOpenOption.READ, StandardOpenOption.CREATE);MappedByteBuffer inMapper = reader.map(MapMode.READ_ONLY, 0, reader.size());MappedByteBuffer outMapper = writer.map(MapMode.READ_WRITE, 0, reader.size());byte[] bye = new byte[inMapper.limit()];inMapper.get(bye);outMapper.put(bye);reader.close();writer.close();基本正常代码使用FileChannel inChannel = FileChannel.open(Paths.get("D:/a.avi"), StandardOpenOption.READ);FileChannel outChannel = FileChannel.open(Paths.get("D:/a1.avi"), StandardOpenOption.CREATE, StandardOpenOption.WRITE);inChannel.transferTo(0, inChannel.size(), outChannel);outChannel.close();inChannel.close();分散(Scatter)与聚集(Gather)分散读取:将通道中的数据分散到多个缓冲区中聚集写入:将多个缓冲区的数据聚集到通道中按照缓冲区的顺序,从 Channel 中读取的数据依次将 Buffer 填满 (图一、分散读取) (图二、聚集写入) 分散(Scatter)与聚集(Gather)代码FileChannel reader = input.getChannel();FileChannel writer = output.getChannel();ByteBuffer buffer = ByteBuffer.allocate(1024);ByteBuffer buffer1 = ByteBuffer.allocate(2024);ByteBuffer[] buffers = new ByteBuffer[]{buffer,buffer1};reader.read(buffers);//分散读取writer.write(buffers);//聚集写入