/data/app/jdk1.8.0_151/bin/java
-Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=7018 -Dcom.sun.management.jmxremote.rmi.port=7019
-Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
-jar ./bussiness-0.0.1-SNAPSHOT.jar
-Xms2048m -Xmx2048m -Xmn1024g -Xss2m -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:ParallelGCThreads=4
-XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=3 -XX:+UseParNewGC
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+PrintGCApplicationConcurrentTime -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -Xloggc:../log/gc.loghtml
jstat -gcutil pid 【间隔时间】 【次数】java
free -h
du -h
df -h正则表达式
EPollArrayWrapper.epollWait 致使CPU占用率太高
CPU占用率高的线程堆栈信息: 线程状态一直是RUNNABLE数组
参见 https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6403933 :安全
这是Linux上poll(和epoll)的问题。已链接套接字的文件描述符在轮询中若是使用掩码0来标识事件,高并发下,大量链接忽然终止(RST),事件集合设置的POLLHUP(POLLERR)位将唤醒选择器!!但因为SocketChannel的事件key为0,这意味着没有任何选定的事件,select不阻塞并当即返回0,将再次进行轮询。并发
须要解决此错误以免在重置链接时选择器旋转。若是事件掩码为0,则能够经过取消注册文件描述符(若是事件集合已更改,则从新注册)来解决此问题。当key为非0时,POLLHUP(POLLERR)将须要转换为就绪集中的OP_READ或OP_WRITE事件,以便应用程序有机会处理IOException。app
解决方案能够参考:
https://blog.csdn.net/zhouhao88410234/article/details/76041702
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=2147719
http://www.javashuo.com/article/p-gkittkpn-t.html
http://www.javashuo.com/article/p-gtgascco-cc.html高并发
对Selector的select操做周期进行统计,每完成一次空的select操做进行一次计数,若在某个周期内连续发生N次空轮询,则触发了epoll死循环bug。重建Selector,判断是不是其余线程发起的重建请求,若不是则将原SocketChannel从旧的Selector上去除注册,从新注册到新的Selector上,并将原来的Selector关闭。oop
netty的解决代码在package io.netty.channel.nio.nioEventLoop这个类下面。性能
上述问题也佐证了: 因NIO要轮询断定,对比BIO而言CPU的占用率可能会高些(BIO在阻塞时会释放CPU资源)。
使用过程当中,使用了错误的方式处理: 每次都从新生成Pattern
Pattern pattern = Pattern.compile(datePattern1); Matcher match = pattern.matcher(sDate);
致使系统线程长时间RUNNING在
Pattern要定义为static final静态变量,以免执行屡次预编译.
private static final Pattern pattern = Pattern.compile(regexRule); private void func(...) { Matcher m = pattern.matcher(content); if (m.matches()) { ... }
在Pattern 的 matcher具体实现中经过synchronized来保证线程安全。
二者在remove指定对象时,都进行了遍历了List。
ArrayList: public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } LinkedList: public boolean remove(Object o) { if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); return true; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; }
经过比较源码:
ArrayList底层实现是数组;LinkedList则是双向链表(内部类Node封装外部Object)
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
总结而言:
LinkedList的性能在修改时仍是比ArrayList要好些。 但不足以支持当前大数据量的测试要求。
选择使用 HashSet!
hashSet的底层实现是经过HashMap来实现hashCode散列定位(hashMap的底层也仍是数组,内部有Node来封装外部数据Object)。
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
public boolean add(E e) { return map.put(e, PRESENT)==null; } public boolean remove(Object o) { return map.remove(o)==PRESENT; }
而hashMap在作查找、put、 remove等操做时,都会先经过对象hashCode计算定位在数组table上的具体存储位置。
public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } public V remove(Object key) { Node<K,V> e; return (e = removeNode(hash(key), key, null, false, true)) == null ? null : e.value; } static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
在具体实践中:
ArrayList.forEach(t -> HashSet.remove(t)) 比 HashSet.removeAll(ArrayList) 效率快。
ArrayList.forEach:
经过遍历数组下标顺序查找对象, hashSet.remove(t) 使用hashMap.remove;
hashSet.removeAll(ArrayList):
使用ArrayList.Iterator()循环获取对象,具体实现也是经过变量数组下标顺序查找;关键在于: 若是size相等,在循环处理过程当中增长了ArrayList.contains断定,会再次循环遍历ArrayList。 时间复杂的从O(n)上升为O(n2)HashSet extends AbstractSet: public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); boolean modified = false; if (size() > c.size()) { for (Iterator<?> i = c.iterator(); i.hasNext(); ) modified |= remove(i.next()); } else { for (Iterator<?> i = iterator(); i.hasNext(); ) { if (c.contains(i.next())) { i.remove(); modified = true; } } } return modified; } ArrayList: public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); final int expectedModCount = modCount; @SuppressWarnings("unchecked") final E[] elementData = (E[]) this.elementData; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { action.accept(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } } ArrayList$Itr: public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; }