jiemin's Blog

本来无一物,何处惹尘埃


  • 首页

  • 归档

  • 标签

单元测试之道Java版读书笔记

发表于 2018-09-26

单元测试

什么是单元测试

单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。

构建单元测试

测试代码必须要做以下这几件事情:

  • 准备测试所需要的各种条件(创建所有必须的对象,分配必要的资源等等)。
  • 调用要测试的方法。
  • 验证被测试方法的行为和期望是否一致
  • 完成后清理各种资源

JUnit的各种断言

Junit提供了一些辅助函数,用于帮助你确定某个被测试函数是否工作正常。通常而言,我们把所有这些函数统称为断言。它让你可以确定:某条件是否为真;两个数是否相等,或者不等,或者其他一些情况。

assertEquals

1
assertEquals([String message],expected,actual)

这是使用得最多的断言形式。在上面的参数中,expected是你的期望值
(通常都是硬编码的),actual是被测试代码实际产生的值,message是~个 可选的消息,如果提供的话,将会在发生错误的时候报告这个消息。当然, 你完全可以不提供这个message参数,而只提供expected和value这两个值。

注意事项

书中的assertEquals方法已经不建议使用,建议使用assertArrayEquals方法

阅读全文 »

java多线程之ForkJoin框架

发表于 2018-09-26

Fork/JOIN框架

简介

Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。

运行流程图

工作窃取模式

工作窃取(work-stealing)算法是指某个线程从其他队列里窃取任务来执行

假如我们需要做一个比较大的任务,我们可以把这个任务分割为若干互不依赖的子任务,为了减少线程间的竞争,于是把这些子任务分别放到不同的队列里,并为每个队列创建一个单独的线程来执行队列里的任务,线程和队列一一对应,比如A线程负责处理A队列里的任务。但是有的线程会先把自己队列里的任务干完,而其他线程对应的队列里还有任务等待处理。干完活的线程与其等着,不如去帮其他线程干活,于是它就去其他线程的队列里窃取一个任务来执行。而在这时它们会访问同一个队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列,被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列的尾部拿任务执行。

工作窃取算法的优点是充分利用线程进行并行计算,并减少了线程间的竞争,其缺点是在某些情况下还是存在竞争,比如双端队列里只有一个任务时。并且消耗了更多的系统资源,比如创建多个线程和多个双端队列。

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
public class ForkJoinCase extends RecursiveTask<Double> {
private static final long serialVersionUID = 1L;
public ForkJoinCase() {
}
// 进行forkJoin的界限,数量少于100直接进行计算
static final int THRESHOLD = 100;
double[] array;
int start;
int end;
ForkJoinCase(double[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
protected Double compute() {
if (end - start <= THRESHOLD) {
// 如果任务足够小,直接计算:
double sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
}
// 任务太大,一分为二:
int middle = (end + start) / 2;
ForkJoinCase subtask1 = new ForkJoinCase(this.array, start, middle);
ForkJoinCase subtask2 = new ForkJoinCase(this.array, middle, end);
invokeAll(subtask1, subtask2);
Double subresult1 = subtask1.join();
Double subresult2 = subtask2.join();
Double result = subresult1 + subresult2;
return result;
}
public static void main(String[] args) {
double[] array = new double[400];
for(int i=0; i<array.length; i++) {
array[i] = Math.random() * 100;
}
// fork/join task:
ForkJoinPool fjp = new ForkJoinPool(4); // 最大并发数4
ForkJoinTask<Double> task = new ForkJoinCase(array, 0, array.length);
long startTime = System.currentTimeMillis();
Double result = fjp.invoke(task);
long endTime = System.currentTimeMillis();
System.out.println("Fork/join sum: " + result + " in " + (endTime - startTime) + " ms.");
}
}
阅读全文 »

ansible学习笔记

发表于 2018-09-25

ansible介绍

Ansible 简单的说是一个配置管理系统,你只需要可以使用 ssh 访问你的服务器或设备就行。你可以将代码部署到任意数量的服务器上.

ansible 架构图

Ansible主要组成部分功能说明

1
2
3
4
5
6
PLAYBOOKS:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YML文件
INVENTORY:Ansible管理主机的清单/etc/anaible/hosts
MODULES:Ansible执行命令的功能模块,多数为内置的核心模块,也可自定义,ansible-doc –l 可查看模块
PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
API:供第三方程序调用的应用程序编程接口
ANSIBLE:组合INVENTORY、 API、MODULES、PLUGINS的绿框,可以理解为是ansible命令工具,其为核心执行工具

注意事项:

  • 执行ansible的主机一般称为主控端,中控,master或堡垒机
  • 主控端Python版本需要2.6或以上
  • 被控端Python版本小于2.4需要安装python-simplejson
  • 被控端如开启SELinux需要安装libselinux-python
  • windows不能做为主控端
  • 如果通过ssh进行连接,需在被控端的authorized_keys中添加主控端的公钥id_rsa.pub的内容,通过ssh-keygen来生成公钥,通过ssh-copy-id -i 公钥路径 -p 端口号 ip来对被控端添加主控端的公钥
阅读全文 »

java中多线程之Executor

发表于 2018-09-21

JAVA的Executor框架

Executor架构示意图

Executor接口

Executor接口是Executor框架中的最基础的部分,定义了一个用于执行Runnable的execute方法,他没有实现类,只有一个子接口ExecutorService

ExecutorService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public interface ExecutorService
extends Executor
{
/**
* 关闭方法,调用后执行之前提交的任务,不再接受新的任务
*/
public abstract void shutdown();
/**
* 将暂停所有等待处理的任务并返回这些任务的列表
*/
public abstract List shutdownNow();
/**
* 判断执行器是否已经关闭
*/
public abstract boolean isShutdown();
/**
* 关闭后所有任务是否都已完成
*/
public abstract boolean isTerminated();
/**
* 中断
*/
public abstract boolean awaitTermination(long l, TimeUnit timeunit)
throws InterruptedException;
/**
* 提交一个Callable任务
*/
public abstract Future submit(Callable callable);
public abstract Future submit(Runnable runnable, Object obj);
/**
* 提交一个Runable任务
*/
public abstract Future submit(Runnable runnable);
public abstract List invokeAll(Collection collection)
throws InterruptedException;
public abstract List invokeAll(Collection collection, long l, TimeUnit timeunit)
throws InterruptedException;
public abstract Object invokeAny(Collection collection)
throws InterruptedException, ExecutionException;
public abstract Object invokeAny(Collection collection, long l, TimeUnit timeunit)
throws InterruptedException, ExecutionException, TimeoutException;
}
阅读全文 »

ab压力测试

发表于 2018-09-12

ab压力测试

安装ab

yum -y install httpd-tools

压力测试命令

ab -n 1000 -c 10 '请求地址'

注意:请求地址需要用引号引起来,否则如果请求地址带参数,请求会不完整

参数说明

  • -A:指定连接服务器的基本的认证凭据;
  • -c:指定一次向服务器发出请求数;
  • -C:添加cookie;
  • -g:将测试结果输出为“gnuolot”文件;
  • -h:显示帮助信息;
  • -H:为请求追加一个额外的头;
  • -i:使用“head”请求方式;
  • -k:激活HTTP中的“keepAlive”特性;
  • -n:指定测试会话使用的请求数;
  • -p:指定包含数据的文件;
  • -q:不显示进度百分比;
  • -T:使用POST数据时,设置内容类型头;
  • -v:设置详细模式等级;
  • -w:以HTML表格方式打印结果;
  • -x:以表格方式输出时,设置表格的属性;
  • -X:使用指定的代理服务器发送请求;
  • -y:以表格方式输出时,设置表格属性。
阅读全文 »

Sentinel安装部署中遇到的坑

发表于 2018-07-17

redis Sentinel介绍

Redis Sentinel是一个分布式架构,包含若干个Sentinel节点和Redis数据节点,每个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当发现节点不可达时,会对节点做下线标识。

如果被标识的是主节点,他还会选择和其他Sentinel节点进行“协商”,当大多数的Sentinel节点都认为主节点不可达时,他们会选举出一个Sentinel节点来完成自动故障转移工作,同时将这个变化通知给Redis应用方。

sentinel 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Sentinel节点的端口
port 26379
dir /var/redis/data/
logfile "26379.log"
// 当前Sentinel节点监控 127.0.0.1:6379 这个主节点
// 2代表判断主节点失败至少需要2个Sentinel节点节点同意
// mymaster是主节点的别名
sentinel monitor mymaster 127.0.0.1 6379 2
//每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒且没有回复,则判定不可达
sentinel down-after-milliseconds mymaster 30000
//当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1
sentinel parallel-syncs mymaster 1
//故障转移超时时间为180000毫秒
sentinel failover-timeout mymaster 180000
// 注意不同的哨兵需要设置不同的myid
sentinel myid 184122c2e00efdee4fd157961fb2d47901d85e23

由于我安装sentinel时是直接复制的sentinel.conf文件,所以文件中的sentinel myid 的值是一样,这样启动多个sentinel时只算一个sentinel,sentinel是通过myid来区分,而不是通过端口号,网上其他的教程没有提到这一点,在此记录一下。

参考文章

  1. Redis 学习笔记(十三)Redis Sentinel 介绍与部署
  2. Redis+Sentinel集群安装与配置

centos安装mysql-udf-http

发表于 2018-06-08

mysql-udf-http

简介

mysql-udf-http 是一款简单的MySQL用户自定义函数,具有http_get()、http_post()、http_put()、http_delete()四个函数,可以在MySQL数据库中利用HTTP协议进行REST相关操作。

应用场景

当mysql数据库表中某一个字段的值发生变化,需要通知业务系统,这个时候就可以使用mysql的触发器及mysql-udf-http来进行http请求的发送。

安装

下载

下载地址:
https://code.google.com/archive/p/mysql-udf-http/downloads

注:需要使用翻墙代理才能下载。

解压文件

tar zxvf mysql-udf-http-1.0.tar.gz

查看mysql安装目录

进入mysql中,在命令行中输入

show variables like "%char%"

如上图所示,该服务器的mysql安装目录为/usr/share/mysql

阅读全文 »

ssh免密配置失效

发表于 2018-06-05

前言

配置jenkins需要设置ssh免密,在jenkins所在主机中生成id_rsa.pub后,将id_rsa.pub追加到想要免密登录主机的.ssh目录下的authorized_keys文件中,但添加完成后还是不能免密登录。

排除问题过程

1 保证用户的.ssh目录权限是700。

2 保证.ssh下的authorized_keys文件是600权限

3 查看selinux,保证selinux为disabled

4 查看/etc/ssh/sshd_config文件,定位到最后。

发现authorizedKeysFile文件指向的是.ssh/KHK75NEOiq,改为.ssh/authorized_keys

5 重启sshd服务

1
service sshd restart

再次尝试连接,不用密码就能登录了,问题解决。

阅读全文 »

postgresql安装及主从部署

发表于 2018-05-02

安装postgresql

使用源码安装

  1. 下载源码包

    1
    wget https://ftp.postgresql.org/pub/source/v9.6.3/postgresql-9.6.3.tar.bz2
  2. 解压

    1
    tar xjvf postgresql-9.6.3.tar.bz2
  3. 进入解压目录,指定安装目录,编译

    1
    2
    3
    ./configure --prefix=/usr/local/pgsql
    make
    make install

configure
时可能会遇到报错,安装对应的依赖

1
2
yum install zlib-devel
yum install readline-devel

添加用户, 设置目录权限

1
2
3
4
adduser postgres
passwd postgres
mkdir -p /usr/local/pgsql/data
chown -R postgres:root /usr/local/pgsql
阅读全文 »

Eclipse在Mac下启动时卡住问题

发表于 2018-04-02

问题

电脑强制关机后重新打开eclipse是在加载界面加载到”org.eclipse.mylyn.tasks.ui” 时卡住了,打不开eclipse了。之前我使用的解决方法是将工作空间下的.metadata目录整个删除,然后eclipse就能重新启动了。但这种解决方式会将eclipse所有的配置给删除了,需要重新设置,比较麻烦。经过网上搜索解决办法,尝试了几种后,确定了一种方法有效,在这里记录一下。

解决办法

  1. 使用命令行窗口进入工作空间目录下,输入cd .metadata/.plugins/org.eclipse.core.resources

  2. 使用rm命令或者手动删除含有snap的文件,例如“7.snap”

  3. 重启Eclipse

1234…6
我爱的乌托邦

我爱的乌托邦

60 日志
23 标签
© 2020 我爱的乌托邦
由 Hexo 强力驱动
主题 - NexT.Pisces