posts - 19, comments - 32, trackbacks - 0, articles - 55
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2017年3月28日

package stacktest;

/**
* @Author: zzz
* @CreateTime: 2017/3/28 10:52
* @Description: 队列特点(先进先出),链表实现的队列 在队头删除元素,在队尾插入元素。
* 这样才能满足队列的特性。
*/
public class MyQueue<T> {
private Node<T> front; //队列头,只能删除元素

    private Node<T> rear; //队列尾,只能用来插入入元素

    private int size;//队列的长度

/**
* 初始化队列
*/
public MyQueue() {
front = new Node<T>();
rear = front;
}

/**
* 链表的数据结构
*/
private class Node<T> {
public T data;
public Node<T> next;

public Node(T data, Node next) {
this.data = data;
this.next = next;
}

public Node(T data) {
this.data = data;
}

public Node() {
}
}

public void add(T data) {
//新插入的节点永远是尾节点,它的next 指向null(即没有后继节点)
        Node newNode = new Node(data, null);
//让尾节点next指向新节点
        rear.next = newNode;
rear = newNode;
size++;
}

public T pop() throws Exception {
if (size < 1) {
throw new Exception("错误,队列为空。");
}
Node<T> nextNode = front.next;

front.next = nextNode.next;
size--;
if (size < 1) {
rear = front;
size = 0;
}
return nextNode.data;

}

//取队首元素

public T peek() throws Exception {
if (size < 1){
throw new Exception("错误,队列为空。");
};
return front.next.data;

}
//返回队列的大小
public int getSize() {
return size;
}

//判断队列是否为空
public boolean isEmpty() {
return size == 0;
}

/**
* 遍历算法,移动front指针,直到front指针追上rear指针
*/
public void traverse(){
for(Node currentNode=front.next; currentNode!=null; currentNode=currentNode.next ){
System.out.println(currentNode.data);
}
}

public static void main(String[] args)throws Exception{
MyQueue<String> queue=new MyQueue<>();
for(int i=0;i<10;i++){
queue.add("88888-"+i);
}

/* for(int i=0;i<10;i++){
String s=queue.pop();
System.out.print(s+";");
}*/
queue.traverse();

}
}

posted @ 2017-03-28 15:48 张钊钊 阅读(1) | 评论 (0)编辑 收藏

2017年3月27日

栈的特点:后进先出,所以一个线性链表实现的栈也只能在一端操作才能满足这种特性;


/**
* @Author: zzz
* @CreateTime: 2017/3/27 14:51
* @Description:
*/
public class MyStack<T> {

private Node top;//永远指向栈顶元素
//元素个数
private int size;


/**
* 内部类,定义节点
*/
private class Node {
public T data;

public Node next;

public Node(T data, Node next) {
this.data = data;
this.next = next;
}

}

public void push(T data) {
//next 指向当前元素top,如果是第一个元素next 指向null;
Node node = new Node(data, top);
//把当前元素指向top
top = node;
size++;
}


public T pop() {
Node oldNode = top;
top = top.next;
oldNode.next = null;
//释放引用
return oldNode.data;
}

//返回栈顶的元素,但不出栈
public T peek() {
return top.data;

}

// 判断链栈是否为空栈
public boolean empty() {
return size == 0;
}

public String toString() {
// 链栈为空链栈时
if (empty())
return "[]";
else {
StringBuilder sb = new StringBuilder("[");
for (Node current = top; current != null; current = current.next) {
sb.append(current.data.toString() + ", ");
}
int len = sb.length();
return sb.delete(len - 2, len).append("]").toString();

}
}

public static void main(String[] args) throws Exception {
MyStack stack = new MyStack<String>();
for (int i = 0; i <= 10; i++) {
stack.push("111111-" + i);
}
System.out.println(stack);
System.out.println("frist pop="+stack.pop());
System.out.println("second pop="+stack.pop());
System.out.println("thrid pop="+stack.pop());
System.out.println("pop 之后的"+stack);
}

posted @ 2017-03-27 15:43 张钊钊 阅读(3) | 评论 (0)编辑 收藏

2017年2月16日

gitlab 有两种提交代码方式 

1:把某一个分支clone到本地,然后修改和增加本地分支的代码,然后commit , 在pull , 在push,

2:把某一个分支clone到本地,然后修改和增加本地分支的代码,然后commit,在fetch , 在rebase 在push.



posted @ 2017-02-16 14:01 张钊钊 阅读(8) | 评论 (0)编辑 收藏

2017年2月9日

1.环境配置

首先安装GitTortoiseGit,不要问我为什么要装TortoiseGit,不知道为什么,就是喜欢小乌龟。

Git下载 
TortoiseGit下载 
这里有打包好的: 
32bit下载 / 64bit下载

安装还是比较简单的,一路默认选项下一步就可以了,因为的我的电脑系统是Windows 10的,安装的时候遇到了2502、2503报错,这是由于安装权限不足造成的,也很好解决,使用命令行安装就好了,戳这里查看解决方法 。

2.配置SSH Key

OK,到这里环境已经安装完成了,接下来就要生成SSH Key了。

首先在TortoiseGit的安装目录下的bin文件夹中找到puttygen.exe这个工具(如果你没有选择安装目录的话,默认路径应该是C:\Program Files\TortoiseGit\bin),这个工具是用来生成密钥对的,打开它点击Generate,然后鼠标在进度条下方不停的晃动,几秒后就会生成密钥对,点击Sava private key保存私钥到本地(输入一个名字,保存到一个你找的到的文件夹),不要关闭这个窗口,接下来还会用到。

生成密钥对

打开GitLab,找到Profile settings(右上角)下的SSH keys选项,选择Add SSH Key,Title输入框里输入一个名称(随便写),然后把上面生成的以ssh-rsa开头的一长串密钥复制到Key输入框,点击Add Key保存。

添加SSH Key

添加SSH Key

到这里SSH Key就配置成功了,刚才生成密钥对的窗口可以关闭了。

3.在本地的项目中配置SSH key

在项目的文件夹上右击鼠标,选择TortoiseGit—Settings—Remot,在Putty Key后选择刚才保存到本地的私钥,然后点击应用。

配置SSH key]

设置SSH客户端,选择Network选项,在下面的SSH Client选项中选择TortoiseGit的安装目录下bin文件夹中的TortoiseGitPlink.exe程序,如果已经默认选中,直接确定就可以了。

设置SSH客户端

在Pull或Push项目的时候,记得勾选Autoload Putty Key选项。

自动加载Putty Key

到这里,GitLab配置SSH Key就已经全部完成了,再也不用麻烦运维的小伙伴了。

GitHub也可以使用此方法配置SSH Key,在Personal settings—SSH and GPG keys—SSH keys选项下选择New SSH Key就可以了。

注意最后clone时候地址使用

URL:  git@git.XXXX.com:ybz/SSC_server.git 前面不用加任任何东西,我就加了ssh://东西弄了好久都clone不下来。

posted @ 2017-02-09 16:33 张钊钊 阅读(6) | 评论 (0)编辑 收藏

2016年12月26日

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * Created by Administrator on 2016/12/26.
 */
public class Test {
    public static void main(String[] args)throws Exception{
        final AtomicInteger sum=new AtomicInteger(0);
        ExecutorService executorService=Executors.newFixedThreadPool(4);
        BlockingQueue<String> queue=new LinkedBlockingDeque<String>(200);
        List<String> list=new LinkedList<String>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("40");
        queue.addAll(list);
        final CountDownLatch cdOrder = new CountDownLatch(list.size());
       for(int i=0 ; i< list.size() ; i++){
           final String sql=queue.poll();
           executorService.execute(new Runnable(){
               @Override
               public void run() {
                   System.out.println("线程" + Thread.currentThread().getName() +";"+sql);
                   cdOrder.countDown(); //任务执行完毕,返回给指挥官,cdAnswer减1。
                   sum.getAndAdd(Integer.parseInt(sql));
               }
           });
       }
       cdOrder.await(2000, TimeUnit.MILLISECONDS);//等待所有线程完成工作2秒内完工
       executorService.shutdown(); //任务结束,停止线程池的所有线程
       System.out.println(sum.get());
    }
}

posted @ 2016-12-26 16:21 张钊钊 阅读(3) | 评论 (0)编辑 收藏

2016年7月6日

首先使用ipconfig 查看 一共有多少个网卡,进行上网路由(其中包括:ip地址,子网掩码,网关)
   
  然后使用route print 命令浏览 路由信息,
  然后使用route -p add 10.12.0.0 mask 255.255.0.0 127.5.1.2  metric 1(路由级别)
  
  
  所以如果内外网都要上网,最好设置外网所有ip走外网网关,然后在指定内网固定IP走内网网关;
  
  即外网路由添加:
   route -p add 0.0.0.0 mask 0.0.0.0 127.5.1.2  metric 1 //是指所以ip走 127.5.1.2这个路由
   
   内网路由指定固定IP:
   
   然后使用route -p add 10.12.0.0 mask 255.255.0.0 127.5.1.2  metric 2(路由级别,一般内网路由级别低)
  
  这句的意思是-p 是永久路由,10.12.0.0 是网自 mask 255.255.0.0是子网掩码  127.5.1.2 是10.12.0.0 这个网段的Ip地址通过 127.5.1.2 这个网关路上发包出去,
  
  比如公司有一个无线外网,另一个是公司内部的研发网,可以用route 命令添加两条路由规则,外网网段的通过一个网关发包,研发网的能过另一个网关发包
  这时候,不用手动切换两个网,计算机会自动切换。这样就可以双网连接了 

posted @ 2016-07-06 11:50 张钊钊 阅读(21) | 评论 (0)编辑 收藏

2016年6月26日

打开jdk下的bin目录 看下能否找到"wsimport.exe"这个文件 
一般情况下都会有 
如果没有则说明你的JDK不支持这个功能 
然后在DOS窗口下输入wsimport 敲回车 
如果提示错误的话 说明你的JDK环境变量还没有配好 

如果OK的话 输入以下命令就可以将wsdl文件生成java文件了 
wsimport http://127.0.0.1/TicketMobile/services/Cococ?wsdl  -keep -p com.llg.ws2 -s g:/ws 


参数说明 
wsimport 这个是必须的 该工具的名称 
http://127.0.0.1/TicketMobile/services/ssc?wsdl  wsdl文件 
-keep  是否生成源文件 
-p nc.ssc.ws2  生成后的java包名 
-s D:/ws    生成后放哪个目录

posted @ 2016-06-26 02:45 张钊钊 阅读(59) | 评论 (0)编辑 收藏

2015年11月6日

多个网关上网,不用进行手动切换,让电脑自己切换方法,使用route命令:
  首先使用ipconfig 查看有多少个适配器上网,进行上网路由(其中包括:ip地址,子网掩码,网关)
   
  然后使用route print 命令浏览 路由信息,
  然后使用route -p add 10.12.0.0 mask 255.255.0.0 127.5.1.2 
  
  这句的意思是-p 是永久路由,10.12.0.0 是网自  mask 255.255.0.0是子网掩码   127.5.1.2 是10.12.0.0 这个网段的Ip地址通过 127.5.1.2 这个网关路由上发包出去,
  
  比如公司有一个无线外网,另一个是公司内部的研发网,可以用route 命令添加两条路由规则,外网网段的通过一个网关发包,研发网的能过另一个网关发包
  这时候,不用手动切换两个网,计算机会自动切换。这样就可以双网连接了 

posted @ 2015-11-06 11:55 张钊钊 阅读(12) | 评论 (0)编辑 收藏

2015年7月31日

1:spring 4 @Scheduled(cron="0/2 * * * * ?") 注释 在容器中不执行的问题!吗的搞啊整整一天,原因是这个引起的: default-lazy-init="true"  这个配置是懒加载,可以配置到ben 标签中,但是我一个同事配置到

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"
       default-lazy-init="true">  spring 标签头中了,导致@Scheduled 中配置的类不加载,使用时候才加载。所以不执行定时任务。大家要注意了。


2: spring 3 以后,有一个<beans profile="product"> 功能 是可以打包时候,随刊切换测试和生产环境配置,但是要注意如果说把war包部暑到容器中(比较tomcat 中)一定激活一个profile;

1:可以在web.xml 中配置 
<context-param>
        <param-name>spring.profiles.default</param-name>
        <param-value>local</param-value>
    </context-param>
2:可以在  JVM启动变量中指定一个比如:'JAVA_HOME':'/opt/apps/jdk1.7.0','JVM_ARGS': '-Dspring.profiles.active=product -Dlog_path=/opt/logs/ -Dappid=11144 -Dfile.encoding=UTF-8 -XX:MaxPermSize=128m -XX:PermSize=128m'}   如果疏忽大意不做配置,导致错误提示是容器启动,老是报依赖注入错误。









posted @ 2015-07-31 14:30 张钊钊 阅读(82) | 评论 (0)编辑 收藏

2015年6月26日

ES索引优化篇主要从两个方面解决问题,一是索引数据过程;二是检索过程。 
索引数据过程我在上面几篇文章中有提到怎么创建索引和导入数据,但是大家可能会遇到索引数据比较慢的过程。其实明白索引的原理就可以有针对性的进行优化。ES索引的过程到相对Lucene的索引过程多了分布式数据的扩展,而这ES主要是用tranlog进行各节点之间的数据平衡。所以从上我可以通过索引的settings进行第一优化: 
1
Java代码  收藏代码
  1. "index.translog.flush_threshold_ops": "100000"  

2
Java代码  收藏代码
  1. "index.refresh_interval": "-1"  

这两个参数第一是到tranlog数据达到多少条进行平衡,默认为5000,而这个过程相对而言是比较浪费时间和资源的。所以我们可以将这个值调大一些还是设为-1关闭,进而手动进行tranlog平衡。第二参数是刷新频率,默认为120s是指索引在生命周期内定时刷新,一但有数据进来能refresh像lucene里面commit,我们知道当数据addDoucment会,还不能检索到要commit之后才能行数据的检索所以可以将其关闭,在最初索引完后手动refresh一之,然后将索引setting里面的index.refresh_interval参数按需求进行修改,从而可以提高索引过程效率。 
另外的知道ES索引过程中如果有副本存在,数据也会马上同步到副本中去。我个人建议在索引过程中将副本数设为0,待索引完成后将副本数按需量改回来,这样也可以提高索引效率。 
“number_of_replicas”: 0 
上面聊了一次索引过程的优化之后,我们再来聊一下检索速度比较慢的问题,其实检索速度快度与索引质量有很大的关系。而索引质量的好坏与很多因素有关。 

一、分片数 
分片数,与检索速度非常相关的的指标,如果分片数过少或过多都会导致检索比较慢。分片数过多会导致检索时打开比较多的文件别外也会导致多台服务器之间通讯。而分片数过少为导至单个分片索引过大,所以检索速度慢。 
在确定分片数之前需要进行单服务单索引单分片的测试。比如我之前在IBM-3650的机器上,创建一个索引,该索引只有一个分片,分别在不同数据量的情况下进行检索速度测试。最后测出单个分片的内容为20G。 
所以索引分片数=数据总量/单分片数 
目前,我们数据量为4亿多条,索引大小为近1.5T左右。因为是文档数据所以单数据都中8K以前。现在检索速度保证在100ms 以下。特别情况在500ms以下,做200,400,800,1000,1000+用户长时间并发测试时最坏在750ms以下. 

二、副本数 
副本数与索引的稳定性有比较大的关系,怎么说,如果ES在非正常挂了,经常会导致分片丢失,为了保证这些数据的完整性,可以通过副本来解决这个问题。建议在建完索引后在执行Optimize后,马上将副本数调整过来。 
大家经常有一个误去副本越多,检索越快,这是不对的,副本对于检索速度其它是减无增的我曾做过实现,随副本数的增加检索速度会有微量的下降,所以大家在设置副本数时,需要找一个平衡值。另外设置副本后,大家有可能会出现两次相同检索,出现出现不同值的情况,这里可能是由于tranlog没有平衡、或是分片路由的问题,可以通过?preference=_primary 让检索在主片分上进行。 

三、分词 
其实分词对于索引的影响可大可小,看自己把握。大家越许认为词库的越多,分词效果越好,索引质量越好,其实不然。分词有很多算法,大部分基于词表进行分词。也就是说词表的大小决定索引大小。所以分词与索引膨涨率有直接链接。词表不应很多,而对文档相关特征性较强的即可。比如论文的数据进行建索引,分词的词表与论文的特征越相似,词表数量越小,在保证查全查准的情况下,索引的大小可以减少很多。索引大小减少了,那么检索速度也就提高了。 

四、索引段 
索引段即lucene中的segments概念,我们知道ES索引过程中会refresh和tranlog也就是说我们在索引过程中segments number不至一个。而segments number与检索是有直接联系的,segments number越多检索越慢,而将segments numbers 有可能的情况下保证为1这将可以提到将近一半的检索速度。 
Java代码  收藏代码
  1. $ curl -XPOST ‘http://localhost:9200/twitter/_optimize? max_num_segments =1′  


五、删除文档 
删除文档在Lucene中删除文档,数据不会马上进行硬盘上除去,而进在lucene索引中产生一个.del的文件,而在检索过程中这部分数据也会参与检索,lucene在检索过程会判断是否删除了,如果删除了在过滤掉。这样也会降低检索效率。所以可以执行清除删除文档。 
Java代码  收藏代码
  1. $ curl -XPOST ‘http://localhost:9200/twitter/_optimize? only_expunge_deletes =true’  

posted @ 2015-06-26 16:00 张钊钊 阅读(44) | 评论 (0)编辑 收藏