java 笔记
时间格式SimpleDateFormat
/************时间**************/
public static final String yyyyMMddHHmmss = "yyyyMMdd HH:mm:ss";
public static final String yyyyMMdd = "yyyyMMdd";
public static final String yyyy_MM_dd = "yyyy-MM-dd";
public static final String HHmmss = "HH:mm:ss";
public static final String yyyyMMddHHmmssSSS = "yyyyMMdd HH:mm:ss:SSS";
public static final String yyyyMMddTHHmmssSSS = "yyyyMMdd'T'HH:mm:ss:SSS";
public static final String HHmmssSSS = "HH:mm:ss:SSS";
public static final String HHmmssSSSZ = "HH:mm:ss.SSS'Z'";
线程安全地使用SimpleDateFormat
//使用ThreadLocal代替原来的new SimpleDateFormat
private static final ThreadLocal<SimpleDateFormat> dateFormatter = new ThreadLocal<SimpleDateFormat>(){
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
https://blog.csdn.net/taoli1986/article/details/52313438
OkHttp添加代理
private static OkHttpClient getOkHttpClient() {
if (okHttpClient == null) {
synchronized (OkHttpV3Client.class) {
if (okHttpClient == null) {
okHttpClient = new OkHttpClient.Builder()
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 1080)))
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.build();
}
}
}
return okHttpClient;
}
java参数传递方式
- 值传递
- 引用传递
获取ip地址
InetAddress ip4 = Inet4Address.getLocalHost();
String url = ip4.getHostAddress();
使用日志方式
方式1:使用lombok.slf4j
1.引入包
compile group: 'org.projectlombok', name: 'lombok', version: '1.18.4'
2.添加@Slf4j注解
方式2:
1.导入包
compile group: 'log4j', name: 'log4j', version: '1.2.17'
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.26'
compile group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.26'
2.使用
Logger logger = LoggerFactory.getLogger(xx.class);
3.spring 日志配置
logging:
file: log.log // 生成文件名
level:
root: WAIN // 日志级别
4.参考https://www.cnblogs.com/lujiango/p/8573411.html
linux java进程分析
- jmap -dump:live,format=b,file=market-data.dump 3132
- 通过mat分析工具分析
同步-异步-阻塞-非阻塞
- 同步和异步关注的是消息通信机制
所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。
换句话说,就是由调用者主动等待这个调用的结果。
而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。
- 阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
java
- 代理模式
父接口,实现类,代理类 - super
继承树,先调用父类构造函数 - 多态
一个接口,多种实现 - 向上转型,ok;向下转型,编码没问题,编译报错
- final方法、类,不能继承
- 数组三种初始化
静态初始化
默认初始化
动态初始化
java
- 自定义注解
@interface - 元注解
@target:描述注解的使用范围
@Retention:描述注解生命周期 - ORM
对象通过注解生成sql生成表 - java动态性:反射
-
反射:运行时加载编译期间未知类
Class.forName("类名"):加载类后,创建类对象,都是同一个对象
String.class
image.png -
通过反射api调用有参构造器对象
image.png -
通过反射api调用普通方法
image.png -
通过反射api获取操作属性
image.png
邮箱正则表达式
eamil:
regex: "^\\w+@(\\w+\\.)+\\w+$" # 邮箱正则表达式
sql自动转换javabean类
http://www.bejson.com/devtools/sql2pojo/
split根据转义符. 、 \等分割
1、如果用“.”作为分隔的话,必须是如下写法:String.split("\."),这样才能正确的分隔开,不能用String.split(".");
2、如果用“|”作为分隔的话,必须是如下写法:String.split("\|"),这样才能正确的分隔开,不能用String.split("|");
“.”和“|”都是转义字符,必须得加"\";
Map,按照插入顺序排序
- LinkedHashMap
加密算法
- md5
// spring加密工具类
import org.springframework.util.DigestUtils
// 加密的长度是固定的32位
eg:public static String getDigestMD5(String sStr) {
String hex = DigestUtils.md5DigestAsHex(sStr.getBytes());
return hex;
long 转 localDate
LocalDate date =
Instant.ofEpochMilli(longValue).atZone(ZoneId.systemDefault()).toLocalDate();
Guava api文档
http://tool.oschina.net/apidocs/apidoc?api=guava
list转map
List<Order> orders = tradeExchangeProxy.getOrders(tradeExchangeProxy.getExhchangeName());
// (value1, value2 )->{ return value2; } :解决duplicate key问题
Map<String, Order> map = orders.stream().
collect(Collectors.toMap(e -> e.getOrderId(), e -> e, (value1, value2 )->{ return value2; }));
linux下使用jstack
- 查找路径
find / -name jstack
- 全路径调用
/usr/local/jdk1.8.0_171/bin/jstack pid
jstack分析,线程状态
https://www.cnblogs.com/hushaojun/p/4323511.html
国际时区 TimeZone ID列表
https://blog.csdn.net/programmer_sir/article/details/8726630
quartz调度任务cron生成工具
http://www.bejson.com/othertools/cron/
java事务回滚
https://blog.csdn.net/qq_34406670/article/details/78945955
泛型
- 泛型就类型的参数
enum枚举值比较
// 如果跟枚举类型比较的不是相同的枚举类,需要.getValue(),enum不能重写hashcode和equals
private BigDecimal function(Integer mode) {
if (SellModeEnum.BUYMODE.getValue().equals(mode)) {
return BigDecimal.ONE;
} else if (SellModeEnum.SELLMODE.getValue().equals(mode)) {
return BigDecimal.ONE;
} else {
throw new RuntimeException("exception");
}
}
// 如果跟枚举类型比较的是相同的枚举类
orders.stream().forEach(o -> {
if (State.BUYMODE.compareTo(o.getState()) == 0 ||
State.SELLMODE.compareTo(o.getState()) == 0) {
positions.add(o);
}
});
String
- 不可变
自动装箱、自动拆箱
"=="和equals()
image.pngimage.png
https://www.bilibili.com/video/av29306544/?p=78
hashcode() 的特性
- HashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,HashCode经常用于确定对象的存储地址;
- 如果两个对象相同, equals方法一定返回true,并且这两个对象的HashCode一定相同;
- 两个对象的HashCode相同,并不一定表示两个对象就相同,即equals()不一定为true,只能说明这两个对象在一个散列存储结构中
-
如果对象的equals方法被重写,那么对象的HashCode也尽量重写。
image.png
hashcode()的作用
image.pngHashMap底层原理
-
HashMap底层结构
image.png - HashMap put方法原理
](https://img.haomeiwen.com/i4428387/97d38d23d160e565.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) -
HashMap put流程
image.png - HashMap put方法
1.先通过k的hashcode和散列算法,算出map的哈希值,定位数组位置
2.再在链表中,通过equals比较k值是否相同
-
扩容问题
image.png -
提高查询效率
image.png -
散列算法
image.png
https://www.bilibili.com/video/av29306544/?p=151
Arrays
// 数组转String
toString
// 数组排序
sort
// 二分法查找
binarySearch
String字符串
// 比较两个字符串(忽略大小写)
equalsIgnoreCase
// 字符串里是否包含字符串
indexOf
// 测试此字符串是否以指定的前缀开头
startsWith
// 测试此字符串是否以指定的后缀结尾
endsWith
// 转小写
toLowerCase
// 转大写
toUpperCase
// 去除收尾空格
trim
断言
Assert.assertTrue(ExTimeOutException.class.isInstance(e));
判断一个对象是否属于某种类型
- instanceof
ConnectException c = e instanceof ConnectException ? ((ConnectException) e) : null;
- isInstance
ExTimeOutException.class.isInstance(e);
Ehcache教程
- 案例中文讲解
https://www.e-learn.cn/content/qita/737272 - 缓存过期策略
https://blog.51cto.com/881206524/2320745?source=dra - 官网案例
http://www.ehcache.org/documentation/3.7/getting-started.html
List
- list迭代器遍历方式
Iterator<StrategyParam> iterator = this.listA.iterator();
//从第一个元素开始遍历,每次获取一个新的元素
while(iterator.hasNext()){
StrategyParam strategyParam = iterator.next();
}
- list修改自身值
// index为下标,some为要设的新值
arr.set(index, some);
异常
- 菜鸟和高手都可能犯的一个错是,在程序有能力处理异常之前就捕获它。
- 异常分类
Java中,异常分为受检查的异常,与执行时异常。
受检查的异常(checkedexceptions),其必须被try{}catch语句块所捕获,或者在方法签名里通过throws子句声明。
执行时异常(runtime exceptions),须要程序猿自己分析代码决定是否捕获和处理,比方 空指针,被0除。Error不须要捕捉。
-
异常处理的15个原则
https://blog.csdn.net/u011983531/article/details/48859129 - image.png
-
检查性异常和运行时异常
https://blog.csdn.net/w405722907/article/details/72831218 -
多个异常统一处理
try {
return OkHttpV3Client.get(url);
} catch (SocketTimeoutException | ConnectException e) {
throw new ExTimeOutException("connect exchange time out");
} catch (IOException e) {
e.printStackTrace();
}
- 自定义异常
public class PositionNullException extends RuntimeException {
public PositionNullException(String msg) {
super(msg);
}
}
字符串转枚举
NameEnum.valueOf(str);
静态导入可以不需要输入类名即可直接引用静态方法
import static com.zyf.common.util.Util.*;
Hutool工具包
java时间操作教程
https://www.bilibili.com/video/av54961959/?p=3
导入lombok
annotationProcessor 'org.projectlombok:lombok:1.18.4'
implementation 'org.projectlombok:lombok:1.18.4'
java项目目录分层概念
- 多模块分层
公司归属.模块.MVC.业务,例如:com.alibaba.strategymanager.controller.strategy
java工具类
Java 开放api接口签名验证(MD5模式)
https://blog.csdn.net/u010096717/article/details/84558463
linux jdk安装
https://baijiahao.baidu.com/s?id=1625872524161069279&wfr=spider&for=pc
LinkedHashMap排序
/**
* 排序
* @param paramMap 参数
* @param comparator 比较器
* @return 本实例对象
*/
public static Map<String, String> sort(LinkedHashMap<String, String> paramMap, Comparator<String> comparator) {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
paramMap.keySet().stream()
.sorted(comparator)
.forEach(k -> map.put(k, paramMap.get(k)));
return map;
}
HmacSHA256编码使用demo
删除字符串最后一个字符
String rtn = rtn.substring(0, rtn.length() - 1);
java excel教程
1.安装apache poi包
https://mvnrepository.com/artifact/org.apache.poi/poi/4.1.0
2.Java利用POI 读取Excel行列数,getLastRowNum()和getLastCellNum()
https://blog.csdn.net/qq_41117947/article/details/79364053
3.分多次将数据写入EXCEL
https://blog.csdn.net/k_520_w/article/details/84349811
4.教程
https://www.cnblogs.com/gdwkong/p/8669220.html
5.文档
https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/Workbook.html
6.追加数据教程
https://blog.csdn.net/qq_24644517/article/details/80733496
java对象排序
1.类继承Comparable接口
2.Comparator
jdk官方默认是升序,是基于:
< return -1
= return 0
> return 1
---------------------
Collections.sort(sos, new Comparator<SimpleOrder>() {
@Override
public int compare(SimpleOrder o1, SimpleOrder o2) {
return o1.price.compareTo(o2.price) == -1 ? -1 : 1;
}
});
如果要降序就必须完全相反:
< return 1
= return 0
> return -1
---------------------
Collections.sort(sos, new Comparator<SimpleOrder>() {
@Override
public int compare(SimpleOrder o1, SimpleOrder o2) {
return o1.price.compareTo(o2.price) == -1 ? 1 : -1;
}
});
https://blog.csdn.net/itmyhome1990/article/details/8952722
https://blog.csdn.net/u013066244/article/details/78997869
java list排序
Collections.sort(list); // 顺序排列
Collections.shuffle(list); // 混乱的意思
Collections.reverse(list); // 倒序排列
时间工具类
TimeUnit
DateUtils
## 程序退出前,钩子函数
// 关闭程序回调
Runtime.getRuntime().addShutdownHook(new Thread(
() -> {
// 关闭netty
this.nettyClose();
running.shutdown();
}));
enum枚举类案例
/**
* @author yuanfeng.z
* @description 市场数据请求类型
* @date 2019/3/27 15:06
*/
public enum MkType {
/**
* k线类型
*/
KLINE("kLine");
private String value;
MkType(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
序列化案例
/**
* @author yuanfeng.z
* @description 交易信息
* @date 2019/3/27 14:47
*/
public class ExchangeInfo implements Serializable {
private static final long serialVersionUID = 1L;
private String exchangeName;
private String symbol;
public ExchangeInfo(String exchangeName, String symbol) {
this.exchangeName = exchangeName;
this.symbol = symbol;
}
}
java加载resources配置文件
public static Properties load(String fileName) {
Properties prop = new Properties();
try(InputStream fis = PropertiesUitl.class.getClassLoader().getResourceAsStream(fileName)) {
prop.load(fis);
} catch (IOException e) {
e.printStackTrace();
}
return prop;
}
java获取resources配置文件路径
/**
* 获取文件路径
* @param c
* @param fileName
* @return
*/
public static String getPath(Class c, String fileName) {
String path = c.getClassLoader().getResource(fileName).getPath();
return path;
}
IDEA 出现错误:找不到或无法加载主类 解决办法
https://blog.csdn.net/angry_mills/article/details/81511130
https://blog.csdn.net/lizongbao1234567890/article/details/78120851
jvm参数
堆最小值:-Xms
堆最大值:-Xmx
每个线程栈大小:-Xss
方法区(静态区)最小值:-XX:PermSize
方法区(静态区)最大值:-XX:MaxPermSize
日志使用教程
2.引用日志
private static Logger log = LoggerFactory.getLogger(InitApplication.class);
3.添加log4j.properties
获取resources文件流
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("config_hedging_exshell-dev.yml");
格式化字符串
String request = String.format("{\"cmd\": {\"type\": 4}, \"type\":1, \"pairs\":[{\"market\":\"%s\",\"coin\":\"%s\"}]}",
"test", "test");
BigDecimal传值一定要用字符串,如果传float或double小数会有精度问题
BigDecimal b = new BigDecimal(0.000001);
BigDecimal比较大小,一定要用compareTo,不能用equals,因为比较0和0.0时不相等
BigDecimal.ZERO.compareTo(level.getBigDecimal(1)) == 0
double转String,解决科学计数法问题
// bug:生成的idStr长度不一定一样
final double size = 100000000000d;
double id = Math.floor(random.nextDouble() * size);
DecimalFormat df = new DecimalFormat("#");
String idStr = df.format(id);
指定double类型值小数位数
// 两位
final double size = 100000000000d;
double id = Math.floor(random.nextDouble() * size);
DecimalFormat df = new DecimalFormat("#.##");
String idStr = df.format(id);
Quartz任务调度管理类
**
* @author yuanfeng.z
* @description 任务调度器
* @date 2019/1/19 10:55
*/
public class QuartzScheduler {
private static List<Scheduler> schedulerList = new ArrayList<>();
public static void add(Scheduler s) {
if (null == s) {
return;
}
schedulerList.add(s);
}
public static void start() {
for (Scheduler s : schedulerList) {
try {
s.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
}
Quartz的使用demo
-
quartz组件关系
image.png - 任务管理器
/**
* @author yuanfeng.z
* @description 任务调度器
* @date 2019/1/19 10:55
*/
public class QuartzScheduler {
public static void addJob(JobDetail j, Trigger t) {
if (null == j || null == t) {
return;
}
try {
Scheduler scheduler = QuartzScheduler.getScheduler();
// 将job加入调度器
scheduler.scheduleJob(j, t);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
public static void start() {
try {
Scheduler scheduler = QuartzScheduler.getScheduler();
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 定义触发的条件
* @param second 触发间隔(秒)
* @param name 触发器名字
* @param group 组名
*/
public static Trigger createTrigger(int second, String name, String group) {
Trigger trigger = newTrigger()
.withIdentity(name, group)
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(second).repeatForever())
.build();
return trigger;
}
/**
* 获取任务调度实例
* @return
* @throws SchedulerException
*/
private static Scheduler getScheduler() throws SchedulerException {
StdSchedulerFactory sf =new StdSchedulerFactory();
Properties props = new Properties();
// 指定调度实例名字
props.put("org.quartz.scheduler.instanceName","orderScheduler");
// 指定调度实例线程数
props.put("org.quartz.threadPool.threadCount","20");
sf.initialize(props);
return sf.getScheduler();
}
}
- 创建job
/**
* 创建摆盘job实例
* @param markingEx
* @param refEx
* @param log
* @return
* @throws SchedulerException
*/
private JobDetail orderJob(Exchange markingEx, Exchange refEx, Logger log, Notice notice, String group) throws SchedulerException {
/**给定时任务传递参数*/
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("markingEx", markingEx);
jobDataMap.put("refEx", refEx);
jobDataMap.put("notice", notice);
jobDataMap.put("riskManager", this.riskManager);
jobDataMap.put("config", this.configMap.get(markingEx.getSymbol()));
jobDataMap.put("log", log);
/**任务*/
JobDetail job = newJob(OrderJob.class)
.withIdentity(markingEx.getSymbol(), group)
.usingJobData(jobDataMap)
.build();
return job;
}
- 实现job
/**
* @author yuanfeng.z
* @description 任务类
* @DisallowConcurrentExecution 等一个任务结束才会执行下一个
* @date 2019/1/18 14:14
*/
// 禁止并发执行多个相同定义的JobDetail
@DisallowConcurrentExecution
public class HedgingJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
/**获取参数*/
Exchange markingEx = (Exchange)context.getJobDetail().getJobDataMap().get("markingEx");
Exchange hedgingEx = (Exchange)context.getJobDetail().getJobDataMap().get("hedgingEx");
Logger log = (Logger)context.getJobDetail().getJobDataMap().get("log");
log.info(markingEx.getSymbol());
}
}
创建线程池工具类
public class HedgingThreadPool {
private ThreadPoolExecutor pool = null;
public void init() {
int corePoolSize = 2;
int maximumPoolSize = 6;
long keepAliveTime = 300;
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(1024);
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
pool = new ThreadPoolExecutor(corePoolSize
, maximumPoolSize
, keepAliveTime
,TimeUnit.SECONDS
, queue
, handler);
}
public void destory() {
if(pool != null) {
pool.shutdownNow();
}
}
public ThreadPoolExecutor getThreadPool() {
return pool;
}
}
启动线程:
pool.execute(new Runnable() {
@Override
public void run() {
}
});
捕获线程异常
1.自定义UncaughtExceptionHandler 类
public class HedgingUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private Logger log;
public HedgingUncaughtExceptionHandler(Logger log) {
this.log = log;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
log.info("捕获到异常");
}
}
2.线程设置异常捕获
HedgingJob g = new HedgingJob();
Thread t = new Thread(g);
HedgingUncaughtExceptionHandler handler = new HedgingUncaughtExceptionHandler(log);
t.setUncaughtExceptionHandler(handler);
t.start();
quartz doc
http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/
java线程池
https://www.cnblogs.com/zedosu/p/6665306.html
jdk1.8 中文文档
https://blog.fondme.cn/apidoc/jdk-1.8-google/
http://www.matools.com/api/java8
时间相加减
1.Calendar
Calendar rightNow = Calendar.getInstance();
rightNow.add(Calendar.DAY_OF_YEAR, 7);
Date expiresDate = rightNow.getTime();