ArrayList源码分析
ArrayList源码分析
- 目标:
- 一、 ArrayList的简介
- 二、ArrayList原理分析
- 2.1 ArrayList的数据结构源码分析
- 2.2 ArrayList默认容量&最大容量
- 2.3 为什么ArrayList查询快,增删慢?
- 2.4 ArrayList初始化容量
- 1、创建ArrayList对象分析:无参数
- 2、创建ArrayList对象分析:带有初始化容量构造方法
- 2.5 ArrayList扩容原理
- 三、ArrayList线程安全问题及解决方案
- 3.1 错误复现
- 3.2 导致ArrayList线程不安全的源码分析
- 3.3 解决方案
- 四、ArrayList的Fail-Fast机制深入理解
目标:
- 理解ArrayList的底层数据结构
- 深入掌握ArrayList查询快,增删慢的原因
- 掌握ArrayList的扩容机制
- 掌握ArrayList初始化容量过程
- 掌握ArrayList出现线程安全问题原因及解决方案
- 掌握ArrayList的Fail-Fast机制
一、 ArrayList的简介
ArrayList
集合是Collection
和List
接口的实现类。底层的数据结构是数组。数据结构特点 : 增删慢,查询快。线程不安全的集合!
许多程序员开发的时候,使用集合基本上无脑选取ArrayList!不建议这种用法。
ArrayList的特点:
- 单列集合 : 对应与Map集合来说【双列集合】
- 有序性 : 存入的元素和取出的元素是顺序是一样的
- 元素可以重复 : 可以存入两个相同的元素
- 含带索引的方法 : 数组与生俱来含有索引【下角标】
二、ArrayList原理分析
2.1 ArrayList的数据结构源码分析
//空的对象数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//默认容量空对象数组,通过空的构造参数生成ArrayList对象实例
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//ArrayList对象的实际对象数组!
transient Object[] elementData; // non-private to simplify nested class access
//1、为什么是Object类型呢?利用面向对象的多态特性,当前ArrayList的可以存储任意引用数据类型。
//2、ArrayList有一个问题,不能存储基本数据类型!就是数组的类型是Object类型
2.2 ArrayList默认容量&最大容量
//默认的初始化容量是10
private static final int DEFAULT_CAPACITY = 10;
//最大容量 : 2^31 - 1 - 8 = 21 4748 3639【21亿】
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
为什么最大容量要-8呢?
目的是为了存储ArrayList集合的基本信息,比如list集合的最大容量!
2.3 为什么ArrayList查询快,增删慢?
ArrayList
的底层数据结构就是一个Object数组
,一个可变的数组,对于其的所有操作都是通过数组来实 现的。
- 数组是一种,查询快、增删慢!
- 查询数据是通过索引定位,查询任意数据耗时均相同。查询效率贼高!
- 删除数据时,要将原始数据删除,同时后面的每个数据迁移。删除效率就比较低!
- 新增数据,在添加数组的位置加入数组,同时在数组后面位置后移以为!添加效率极低!
2.4 ArrayList初始化容量
ArrayList底层是数组,动态数组!
- 底层是Object对象数组,数组存储的数据类型是Object,数组名字为elementData。
transient Object[] elementData; // non-private to simplify nested class access
1、创建ArrayList对象分析:无参数
创建ArrayList的之后,ArrayList容量是多少呢?回答10是错误的!回答0是正确【限定条件,在
JDK1.8中】
如何 初始化 动态数组的容量?10个
构造方法
/*** Constructs an empty list with an initial capacity of ten. */
//空参构造时,创建一个空数组
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//空数组!
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
在执行add()方法的时候初始化!【懒加载】
判断当前数组的容量是否有存储空间,如果没有初始化一个10的容量。
//向数组中,添加一个元素
public boolean add(E e) {//确保有容量,如果第一次添加,会初始化一个容量为10的list //size当前集合元素的个数,随着添加的元素递增ensureCapacityInternal(size + 1); // Increments modCount!! //添加元素elementData[size++] = e; return true;
}
//ensureCapacityInternal确保有容量,如果第一次添加,会初始化一个容量为10的list
private void ensureCapacityInternal(int minCapacity) {//两个方法ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// calculateCapacity(elementData, minCapacity) 拿着当前ArrayList的数组,与当前数组中的元素个数。计算容量
private static int calculateCapacity(Object[] elementData, int minCapacity)
{//ArrayList的数组与默认的数组进行比较。 //{} == {}if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {/true //DEFAULT_CAPACITY = 10//minCapacity 1 //1和10比谁大 10return Math.max(DEFAULT_CAPACITY, minCapacity);//计算之后,返回的初始化容量是10}return minCapacity;
}
// ensureExplicitCapacity() 确保不会超过数组的真实容量
private void ensureExplicitCapacity(int minCapacity) { //minCapacity 当前计算后容量 10modCount++;//对当前数组操作计数器 // overflow-conscious code//最小的容量: 10 - 当前数组的容量{} 0if (minCapacity - elementData.length > 0) grow(minCapacity);//做了扩容
}
2、创建ArrayList对象分析:带有初始化容量构造方法
//创建ArrayList集合,并且设置固定的集合容量
public ArrayList(int initialCapacity) { //initialCapacity 手动设置的初始化容量if (initialCapacity > 0) {//判断容量是否大于0,如果大于0 //创建一个对象数组位指定容量大小,并且交给ArrayList对象 this.elementData = new Object[initialCapacity]; //如果设置的容量为0,设置默认数组} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;//默认的元素数据数组{} } else {//如果不是0,也不是大于0的数,会抛出非法参数异常!throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}
}
注意 : 使用ArrayList的集合,建议如果知道集合的大小,最好提前设置。提示集合的使用效率!
2.5 ArrayList扩容原理
add方法先要确保数组的容量足够,防止数组已经填满还往里面添加数据造成数组越界:
- 如果数组空间足够,直接将数据添加到数组中
- 如果数组空间不够了,则进行扩容。扩容1.5倍扩容。
- 扩容 : 原始数组copy新数组中,同时向新数组后面加入数据
注意 : new的ArrayList的对象没有容量的,在第一次添加的add,会进行第一次扩容。0 -> 10!
//grow扩容数组
private void grow(int minCapacity) {//minCapacity 当前数组的最小容量,存储了多少个元素 // overflow-conscious code//获取当前存储数据数组的长度int oldCapacity = elementData.length;//新的容量 = 旧的容量 + 扩容的容量【旧容量/2 = 0.5旧容量】 //扩容1.5倍扩容int newCapacity = oldCapacity + (oldCapacity >> 1); //极端情况过滤 : 新的容量 - 旧的容量小于0【int值移除】 if (newCapacity - minCapacity < 0)newCapacity = minCapacity;//不扩容了 //新的容量,比ArrayList的最大值,还要大if (newCapacity - MAX_ARRAY_SIZE > 0)//设置新的容量为ArrayList的最大值,以ArrayList最大值为当前容量 newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity);
}
总结:
- 扩容的规则并不是翻倍,是原来容量的1.5倍
- ArrayList的数组最大值Integer.MAX_VALUE。不允许超过这个最大值
- 新增元素时,没有严格的数据值的检查。所有可用设置null
三、ArrayList线程安全问题及解决方案
3.1 错误复现
ArrayList 我们都知道底层是以数组方式实现的,实现了可变大小的数组,它允许所有元素,包括null。
看下面一个例子:开启多个线程操作List集合,向ArrayList中增加元素,同时去除元素
//全局线程共享集合ArrayListprotected static ArrayList<Object> arrayList = new ArrayList<>();@Testvoid arrayListTest() {//1.创建线程数组【500】Thread[] threads = new Thread[500];//2.遍历数组,向线程中添加500个线程对象for (int i = 0; i < threads.length; i++) {threads[i] = new MyThread();threads[i].start();//启动线程}//3.遍历线程,等待线程执行完毕【等待所有线程执行完毕】for (int i = 0; i < threads.length; i++) {try {threads[i].join();//等待线程执行完毕} catch (InterruptedException e) {e.printStackTrace();}}//线程执行内容 : 向集合中添加自己的线程名称//4.遍历list集合,获取所有线程的名称for (Object threadName : arrayList) {System.out.println("threadName = " + threadName);}}//线程执行内容,是想集合中添加自己的线程名称class MyThread extends Thread {@Overridepublic void run() {try {//线程休眠1000Thread.sleep(1000);//向集合中添加自己的线程名称【操作共享内容,会出现线程安全问题】arrayList.add(Thread.currentThread().getName());} catch (InterruptedException e) {e.printStackTrace();}}}
运行代码结果可知,会出现以下几种情况:
- ①打印null
- ②某些线程并未打印
- ③数组角标越界异常
3.2 导致ArrayList线程不安全的源码分析
ArrayList成员变量
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{//ArrayList的Object的数组存所有元素。transient Object[] elementData; // non-private to simplify nested class
access//size变量保存当前数组中元素个数。 private int size;
//...
}
- ArrayList的Object的数组存储所有元素。
- size变量保存当前数组中元素个数。
出现线程不安全源码之一 : add()方法
public boolean add(E e) {//确保有容量,如果第一次添加,会初始化一个容量为10的list //size当前集合元素的个数,随着添加的元素递增ensureCapacityInternal(size + 1); // Increments modCount!! //添加元素elementData[size++] = e; return true;
}
add添加元素,实际做了两个大的步骤:
- 判断elementData数组容量是否满足需求
- 在elementData对应位置上设置值
线程不安全的隐患【1】,导致③数组下标越界异常
线程不安全的隐患【2】,导致①Null、②某些线程并未打印
致①Null、②某些线程并未打印深层次原因是因为多线程情况下出现了指令重排和不保证原子性问题。详见Volatile关键字
由此我们可以得出,在多线程情况下操作ArrayList 并不是线性安全的。
3.3 解决方案
第一种方案:使用Vector集合,Vector集合是线程安全的
//线程安全问题解决方案1
protected static Vector<Object> vector = new Vector<>();
第二种方案:使用Collections.synchronizedList。它会自动将我们的list方法进行改变,最后返回给我们加锁了List
//线程安全问题解决方案2
//将集合改为同步集合
protected static List<Object> synList = Collections.synchronizedList(arrayList);
第三种方案:使用JUC中的CopyOnWriteArrayList类进行替换。
//线程安全问题解决方案3 JUC 【最佳选择】
protected static CopyOnWriteArrayList<Object> copyOnWriteArrayList = new
CopyOnWriteArrayList<>();
因为CopyOnWriteArrayList中的add操作使用了lock锁保证了原子性同时保证线程安全,而且数组也使用了volatile关键字,保证可见性和防止指令重排
四、ArrayList的Fail-Fast机制深入理解
什么是Fail-Fast机制?
"快速失败"即Fail-Fast机制,它是Java中一种错误检测机制!
当多钱程对集合进行结构上的改变,或者在迭代元素时直接调用自身方法改变集合结构而没有通知迭代器时,有可能会触发Fail-Fast机制并抛出异常【ConcurrentModificationException】。注意,是有可能
触发Fail-Fast,而不是肯定!
触发时机 : 在迭代过程中,集合的结构发生改变,而此时迭代器并不知情,或者还没来得及反应,便会
产生Fail-Fast事件。
再次强调,迭代器的快速失败行为无法得到保证!一般来说,不可能对是否出现不同步并发修改,或者
自身修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。
Java.util包中的所有集合类都是快速失败的,而java.util.concurrent包中的集合类都是安全失败的;快
速失败的迭代器抛出ConcurrentModificationException,而安全失败的迭代器从不抛出这个异常。
ArrayList的Fast-Fail事件复现及解决方案
/*** 目标: 复现Fast_Fail机制* 1.产生条件 :* 当多线程操作同一个集合* 同时遍历这个集合,该集合被修改!* 2.解决方案 :使用并发编程包中的集合,CopyOnWriteArrayList替换原有ArrayList集合。*///定义全局共享集合 :static ArrayList<String> list = new ArrayList<>();//Fast_Fail机制CopyOnWriteArrayList// static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();@Testvoid arrayListTest() {//创建线程1,并且向集合添加元素,打印集合中的内容Thread thread1 = new Thread(() -> {//并且向集合添加元素for (int i = 0; i < 6; i++) {list.add("" + i);// 打印集合中的内容printAll();}});thread1.start();//启动线程1//创建线程2,并且向集合添加元素,打印集合中的内容Thread thread2 = new Thread(() -> {//并且向集合添加元素for (int i = 10; i < 16; i++) {list.add("" + i);// 打印集合中的内容printAll();}});thread2.start();//启动线程2}/*** 使用迭代器打印集合*/public static void printAll() {//获取当前集合的迭代器Iterator<String> iterator = list.iterator();//通过迭代器遍历集合while (iterator.hasNext()) {String value = iterator.next();System.out.println(value + ",");}}
使用ArrayList在多线程情况下添加元素时出线ConcurrentModificationException
解决办法使用并发编程包中的集合,CopyOnWriteArrayList替换原有ArrayList集合。
扩展连接
ArrayList集合底层原理
ArrayList集合特点为什么是增删慢、查询快
相关文章:
ArrayList源码分析
ArrayList源码分析目标:一、 ArrayList的简介二、ArrayList原理分析2.1 ArrayList的数据结构源码分析2.2 ArrayList默认容量&最大容量2.3 为什么ArrayList查询快,增删慢?2.4 ArrayList初始化容量1、创建ArrayList对象分析:无参数2、创建A…...
SpringBoot IOC、DI、@Autowired、@Resource、作用域
一、初识Spring1.1 Spring是什么Spring是一个轻量级Java开发框架,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的开源框架,为开发Java应用程序提供全面的基础架构支持。Spring负责基础架构,Java开发者可以专…...
链表相关oj题
1.Leetcode203 移除链表元素 解题思路:从头节点开始进行元素删除,每删除一个元素,需要重新链接节点 struct ListNode* removeElements(struct ListNode* head, int val){struct ListNode*dummyheadmalloc(sizeof(struct ListNode));dummyhea…...
【Linux】操作系统(Operator System)
操作系统(Operator System )一、操作系统的概念二、操作系统的作用三、系统调用和库函数一、操作系统的概念 操作系统是一组控制和管理计算机软硬件资源,为用户提供便捷使用的计算机程序的集合,是配置在计算机硬件系统上的第一层…...
机器学习自学笔记——感知机
感知机预备知识 神经元 感知机算法最初是由科学家从脑细胞的神经凸起联想而来。如下图,我们拥有三个初始xxx值,x1,x2,x0x_1,x_2,x_0x1,x2,x0。其中x01x_01x01为一个初始的常量,专业上称作“偏置”。每个xxx的值都会乘上一个权重…...
C++ Primer第五版_第三章习题答案(21~30)
文章目录练习3.21练习3.22练习3.23练习3.24练习3.25练习3.26练习3.27练习3.28练习3.29练习3.30练习3.21 请使用迭代器重做3.3.3节的第一个练习。 #include <vector> #include <iterator> #include <string> #include <iostream>using std::vector; usi…...
colmap+openmvs进行三维重建流程全记录
window下的colmapopenmvs进行三维重建流程全记录 1.colmap安装与配置 可参考:https://blog.csdn.net/weixin_44153180/article/details/129334018?spm1001.2014.3001.5501 2.openmvs安装与配置 可参考:https://blog.csdn.net/rdw1246010462/article…...
yolov8命令行运行参数详解
序言 整理来自yolov8官方文档常用的一些命令行参数,官方文档YOLOv8 Docs yolov8命令行的统一运行格式为: yolo TASK MODE ARGS其中主要是三部分传参: TASK(可选) 是[detect、segment、classification]中的一个。如果没有显式传递…...
分布式锁简介
Redis因为单进程、性能高常被用于分布式锁;锁在程序中作用是同步工具,保证共享资源在同一时刻只能被一个线程访问。 Java中经常用的锁synchronized、Lock,但是Java的锁智能保证单机的时候有效,分布式集群环境就无能为力了…...
【嵌入式Linux学习笔记】Linux驱动开发
Linux系统构建完成后,就可以基于该环境方便地进行开发了,相关的开发流程与MCU类似,但是引入了设备树的概念,编写应用代码要相对复杂一点。但是省去了很多配置工作。 学习视频地址:【正点原子】STM32MP157开发板 字符…...
2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛(同步赛)(H题)(线段树)
又到了万物复苏的季节,家乡的苹果树结果了。像往常一样小龙同学被叫回家摘苹果。 假设需要采摘的一棵树上当前有a颗苹果,那么小龙会采摘⌈a/3⌉颗苹果,其中⌈x⌉表示不小于x的最小整数。 但是,为了可持续发展,若a小于1…...
Linux内核Thermal框架详解十三、Thermal Governor(3)
接前一篇文章Linux内核Thermal框架详解十二、Thermal Governor(2) 二、具体温控策略 上一篇文章介绍并详细分析了bang_bang governor的源码。本文介绍第2种温控策略:fair_share。 2. fair_share fair_share governor总的策略是频率档位⽐较…...
TikTok品牌出海创世纪(二)
目录 1.推荐算法打造王者品牌 2.品牌聚焦海外Z群体 3.持续扩展应用场景 加速品牌全球化传播 品牌聚焦海外Z群体 “这个地球上,三分之二的人都在用Facebook“,这是对Facebook曾经统治地位最直观的描述。 但如今,这家全球社交媒体巨头的光环正…...
iOS中SDK开发 -- cocoapods库创建
在iOS项目中,经常使用cocoadpods来进行依赖管理以及三方库引入等。引入的三方库一般会有几种形式:一、在Pods目录下可以直接看到源代码的开源库,如AFNetworking,Masonry等常见开源库。二、在Pods目录下拉取的项目文件只能看到对应…...
2023年了,还是没学会内卷....
先做个自我介绍:我,普本,通信工程专业,现在飞猪干软件测试,工作时长两年半。 回望疫情纪元,正好是实习 毕业这三年。要说倒霉也是真倒霉,互联网浪潮第三波尾巴也没抓住,狗屁造富神…...
chatGPT爆火,什么时候中国能有自己的“ChatGPT“
目录 引言 一、ChatGPT爆火 二、中国何时能有自己的"ChatGPT" 三、为什么openai可以做出chatGPT? 四、结论 引言 随着人工智能技术的不断发展,自然语言处理技术也逐渐成为了研究的热点之一。其中,ChatGPT作为一项领先的自然语言处理技术…...
【Matlab算法】粒子群算法求解一维非线性函数问题(附MATLAB代码)
MATLAB求解一维非线性函数问题前言正文函数实现(可视化处理)可视化结果前言 一维非线性函数是指函数的自变量和因变量都是一维实数,而且函数的形式是非线性的,也就是不符合线性函数的形式。在一维非线性函数中,自变量…...
2023 最新发布超全的 Java 面试八股文,整整 1000道面试题,太全了
作为一名优秀的程序员,技术面试都是不可避免的一个环节,一般技术面试官都会通过自己的方式去考察程序员的技术功底与基础理论知识。 2023 年的互联网行业竞争越来越严峻,面试也是越来越难,很多粉丝朋友私信希望我出一篇面试专题或…...
产品经理面经|当面试官问你还有什么问题?
相信很多产品经理在跳槽面试的时候,在面试尾声都会遇到这样的环节,面试官会问你有什么问题要问的,一般来说大家都能随时随地甩出几个问题来化解,但其实在这个环节对于应聘者来说也是一个很好的机会来展现自己的能力,甚…...
单链表的基本操作
目录 一.链表的基本概念和结构 二.链表的分类 三.单链表的基本操作 1.创建一个节点 2.打印 3.尾插 4.头插 5.尾删 6.头删 7.查找 8.指定位置插入 9.指定位置删除 10.销毁 一.链表的基本概念和结构 概念:链表是一种物理存储结构上非连续、非顺序的存储结…...
【微信小程序-原生开发】系列教程目录(已完结)
01-注册登录账号,获取 AppID、下载安装开发工具、创建项目、上传体验 https://sunshinehu.blog.csdn.net/article/details/128663679 02-添加全局页面配置、页面、底部导航 https://sunshinehu.blog.csdn.net/article/details/128705866 03-自定义底部导航&#x…...
JavaEE--Thread 类的基本用法(不看你会后悔的嘿嘿)
Thread类是JVM用来管理线程的一个类,换句话说,每个线程都唯一对应着一个Thread对象. 因此,认识和掌握Thread类弥足重要. 本文将从 线程创建线程中断线程等待线程休眠获取线程实例 等方面来进行具体说明. 1)线程创建 方法1:通过创建Thread类的子类并重写run () 方法 class M…...
MySQL数据库基本使用(二)-------数据库及表的增删改查及字符集修改
1.MySQL数据库的使用演示 1.1创建自己的数据库 命令格式如下(创建的数据库名称不能与已经存在的数据库重名): mysql> create database 数据库名;例如: mysql> create database atguigudb; #创建atguigudb数据库…...
互联网摸鱼日报(2023-03-17)
互联网摸鱼日报(2023-03-17) InfoQ 热门话题 开源新生代的成长之路:从校园到开源,需要迈过哪些挑战? 从 Clickhouse 到 Apache Doris,慧策电商 SaaS 高并发数据服务的改造实践 刚刚,百度文心…...
【前后端】低代码平台Jeecg-Boot 3.2宝塔云服务器部署流程
1 后端 部署流程 修改配置文件 更改数据库、redis的配置。 在system子模块中的target文件夹下生成 jar 包jeecg-boot-module-system-3.2.0.jar。 复制到云服务器 生成数据库 在这里插入图片描述 使用命令运行后端程序 java -jar ./jeecg-boot-module-system-3.2.0.jar宝…...
leetcode todolist
数组 数组的改变、移动 453. 最小移动次数使数组元素相等 665. 非递减数列 283. 移动零 数组的旋转 189. 旋转数组 396. 旋转函数 统计数组中的元素 645. 错误的集合 697. 数组的度 448. 找到所有数组中消失的数字 442. 数组中重复的数据 41. 缺失的第一个正数 数…...
改进YOLO系列 | CVPR2023最新 PConv | 提供 YOLOv5 / YOLOv7 / YOLOv7-tiny 模型 YAML 文件
DWConv是Conv的一种流行变体,已被广泛用作许多神经网络的关键构建块。对于输入 I ∈ R c h w I \in R^{c \times h \times w} I∈...
像ChatGPT玩转Excel数据
1.引言 最近ChatGPT的出现,把人工智能又带起了一波浪潮。机器人能否替代人类又成了最近热门的话题。 今天我们推荐的一个玩法和ChatGPT有点不一样。我们的课题是“让用户可以使用自然语言从Excel查询到自己想要的数据”。 要让自然语言可以从Excel中查数据&#…...
云原生之docker容器监控详解(cAdvisor、node exporter、prometheus)
docker容器监控一、前言二、cAdvisor2.1、安装cAdvisor2.2、使用Prometheus监控cAdvisor2.3、cAdvisor暴露的Prometheus指标三、Node Exporter3.1、安装Node Exporter3.2、指标四、Prometheus4.1、安装4.2、规则配置4.3、报警管理器五、grafana一、前言 cAdvisor源码 node exp…...
<Linux>进程概念
文章目录一、什么是进程1.进程概念2.进程描述 – PCB3.task_struct内容分类二、进程的基本操作1.查看进程2.结束进程3.通过系统调用获取进程标示符4.通过系统调用创建子进程(fork)三、进程状态1.普遍的操作系统状态2.Linux操作系统状态四、两种特殊的进程1.僵尸进程2.孤儿进程五…...
商丘幼儿园网站建设策划方案/一个网站可以优化多少关键词
鉴于ServerSocket的accept方法是阻塞的,那么只能通过多线程的方式实现多客户端连接与服务器连接 基本步骤: 1,服务端创建ServerSocket绑定端口号,循环调用accept()方法 2,客户端创建一个socket并请求和服务器端连接 3,服务器端接受客户端请求&#x…...
烟台做网站系统/关键词三年级
在使用vxe-table 下拉选时遇到一个问题选中后值不显示(针对这个问题做一下记录)图:选择前选择后值不显示代码如下<解决方法:给下拉选加change事件 在事件触发时使单元格清除激活状态,然后立刻将该单元格设置为激活状态.<js代码selectChange效果:选择前选择后值显示了...
政府网站建设情况/网络外包
本文记录了mysql 8.0.15 安装配置的方法,供大家参考,具体内容如下1. MySQL安装1.1 在MySQL官网 下载 Windows 版本的 MySQL 安装包下载地址点击下载Download后会弹出以下界面,点击 No thanks, just start my download1.2 下载完后解压&#x…...
中牟网站建设/网址域名注册
ESG使用指南:1.ESG操作文档网站:ESG有个网站,是专门的操作文档网站,因为ESG三个环境,流程各不一样。地址:http://10.20.12.90:20567/esg-help-doc/2.ESG管理平台网站,分别管理开发,测…...
印度做网站/网络销售公司经营范围
接下来就是我要介绍的论文Zhou D, Frmont V, Quost B, et al. Moving Object Detection and Segmentation in Urban Environments from a Moving Platform ☆[J]. Image & Vision Computing, 2017, 68.这是一篇2017 的论文,发表在HAL,HAL is a multi…...
寻花问柳一家专门做男人的网站/网上培训
Design Principles 这些设计原则能优化Android用户体验并使激发用户的最大兴趣,当你设计思考时要时刻想着他们,不要偏离目标。 打动我 用惊奇的方式吸引我 漂亮的界面,精心放置的动画,适时的声音反馈都是美好的体验,敏…...