時間格式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參數(shù)傳遞方式
- 值傳遞
- 引用傳遞
獲取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.導(dǎo)入包
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進(jìn)程分析
- jmap -dump:live,format=b,file=market-data.dump 3132
- 通過mat分析工具分析
同步-異步-阻塞-非阻塞
- 同步和異步關(guān)注的是消息通信機(jī)制
所謂同步,就是在發(fā)出一個調(diào)用時,在沒有得到結(jié)果之前,該調(diào)用就不返回。但是一旦調(diào)用返回,就得到返回值了。
換句話說,就是由調(diào)用者主動等待這個調(diào)用的結(jié)果。
而異步則是相反,調(diào)用在發(fā)出之后,這個調(diào)用就直接返回了,所以沒有返回結(jié)果。換句話說,當(dāng)一個異步過程調(diào)用發(fā)出后,調(diào)用者不會立刻得到結(jié)果。而是在調(diào)用發(fā)出后,被調(diào)用者通過狀態(tài)、通知來通知調(diào)用者,或通過回調(diào)函數(shù)處理這個調(diào)用。
- 阻塞和非阻塞關(guān)注的是程序在等待調(diào)用結(jié)果(消息,返回值)時的狀態(tài).
阻塞調(diào)用是指調(diào)用結(jié)果返回之前,當(dāng)前線程會被掛起。調(diào)用線程只有在得到結(jié)果之后才會返回。
非阻塞調(diào)用指在不能立刻得到結(jié)果之前,該調(diào)用不會阻塞當(dāng)前線程。
java
- 代理模式
父接口,實(shí)現(xiàn)類,代理類 - super
繼承樹,先調(diào)用父類構(gòu)造函數(shù) - 多態(tài)
一個接口,多種實(shí)現(xiàn) - 向上轉(zhuǎn)型,ok;向下轉(zhuǎn)型,編碼沒問題,編譯報錯
- final方法、類,不能繼承
- 數(shù)組三種初始化
靜態(tài)初始化
默認(rèn)初始化
動態(tài)初始化
java
- 自定義注解
@interface - 元注解
@target:描述注解的使用范圍
@Retention:描述注解生命周期 - ORM
對象通過注解生成sql生成表 - java動態(tài)性:反射
-
反射:運(yùn)行時加載編譯期間未知類
Class.forName("類名"):加載類后,創(chuàng)建類對象,都是同一個對象
String.class
image.png -
通過反射api調(diào)用有參構(gòu)造器對象
image.png -
通過反射api調(diào)用普通方法
image.png -
通過反射api獲取操作屬性
image.png
郵箱正則表達(dá)式
eamil:
regex: "^\\w+@(\\w+\\.)+\\w+$" # 郵箱正則表達(dá)式
sql自動轉(zhuǎn)換javabean類
http://www.bejson.com/devtools/sql2pojo/
split根據(jù)轉(zhuǎn)義符. 、 \等分割
1、如果用“.”作為分隔的話,必須是如下寫法:String.split("\."),這樣才能正確的分隔開,不能用String.split(".");
2、如果用“|”作為分隔的話,必須是如下寫法:String.split("\|"),這樣才能正確的分隔開,不能用String.split("|");
“.”和“|”都是轉(zhuǎn)義字符,必須得加"\";
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 轉(zhuǎn) localDate
LocalDate date =
Instant.ofEpochMilli(longValue).atZone(ZoneId.systemDefault()).toLocalDate();
Guava api文檔
http://tool.oschina.net/apidocs/apidoc?api=guava
list轉(zhuǎn)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
- 全路徑調(diào)用
/usr/local/jdk1.8.0_171/bin/jstack pid
jstack分析,線程狀態(tài)
https://www.cnblogs.com/hushaojun/p/4323511.html
國際時區(qū) TimeZone ID列表
https://blog.csdn.net/programmer_sir/article/details/8726630
quartz調(diào)度任務(wù)cron生成工具
http://www.bejson.com/othertools/cron/
java事務(wù)回滾
https://blog.csdn.net/qq_34406670/article/details/78945955
泛型
- 泛型就類型的參數(shù)
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()


https://www.bilibili.com/video/av29306544/?p=78
hashcode() 的特性
- HashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,HashCode經(jīng)常用于確定對象的存儲地址;
- 如果兩個對象相同, equals方法一定返回true,并且這兩個對象的HashCode一定相同;
- 兩個對象的HashCode相同,并不一定表示兩個對象就相同,即equals()不一定為true,只能說明這兩個對象在一個散列存儲結(jié)構(gòu)中
-
如果對象的equals方法被重寫,那么對象的HashCode也盡量重寫。
image.png
hashcode()的作用

HashMap底層原理
-
HashMap底層結(jié)構(gòu)
image.png - HashMap put方法原理
](https://upload-images.jianshu.io/upload_images/4428387-97d38d23d160e565.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) -
HashMap put流程
image.png - HashMap put方法
1.先通過k的hashcode和散列算法,算出map的哈希值,定位數(shù)組位置
2.再在鏈表中,通過equals比較k值是否相同
-
擴(kuò)容問題
image.png -
提高查詢效率
image.png -
散列算法
image.png
https://www.bilibili.com/video/av29306544/?p=151
Arrays
// 數(shù)組轉(zhuǎn)String
toString
// 數(shù)組排序
sort
// 二分法查找
binarySearch
String字符串
// 比較兩個字符串(忽略大小寫)
equalsIgnoreCase
// 字符串里是否包含字符串
indexOf
// 測試此字符串是否以指定的前綴開頭
startsWith
// 測試此字符串是否以指定的后綴結(jié)尾
endsWith
// 轉(zhuǎn)小寫
toLowerCase
// 轉(zhuǎn)大寫
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 - 官網(wǎng)案例
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為下標(biāo),some為要設(shè)的新值
arr.set(index, some);
異常
- 菜鳥和高手都可能犯的一個錯是,在程序有能力處理異常之前就捕獲它。
- 異常分類
Java中,異常分為受檢查的異常,與執(zhí)行時異常。
受檢查的異常(checkedexceptions),其必須被try{}catch語句塊所捕獲,或者在方法簽名里通過throws子句聲明。
執(zhí)行時異常(runtime exceptions),須要程序猿自己分析代碼決定是否捕獲和處理,比方 空指針,被0除。Error不須要捕捉。
異常處理的15個原則
https://blog.csdn.net/u011983531/article/details/48859129-
優(yōu)秀博客
https://www.zhihu.com/question/28254987
image.png 檢查性異常和運(yùn)行時異常
https://blog.csdn.net/w405722907/article/details/72831218多個異常統(tǒng)一處理
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);
}
}
字符串轉(zhuǎn)枚舉
NameEnum.valueOf(str);
靜態(tài)導(dǎo)入可以不需要輸入類名即可直接引用靜態(tài)方法
import static com.zyf.common.util.Util.*;
Hutool工具包
java時間操作教程
https://www.bilibili.com/video/av54961959/?p=3
導(dǎo)入lombok
annotationProcessor 'org.projectlombok:lombok:1.18.4'
implementation 'org.projectlombok:lombok:1.18.4'
java項目目錄分層概念
- 多模塊分層
公司歸屬.模塊.MVC.業(yè)務(wù),例如: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 參數(shù)
* @param comparator 比較器
* @return 本實(shí)例對象
*/
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行列數(shù),getLastRowNum()和getLastCellNum()
https://blog.csdn.net/qq_41117947/article/details/79364053
3.分多次將數(shù)據(jù)寫入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.追加數(shù)據(jù)教程
https://blog.csdn.net/qq_24644517/article/details/80733496
java對象排序
1.類繼承Comparable接口
2.Comparator
jdk官方默認(rèn)是升序,是基于:
< 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
## 程序退出前,鉤子函數(shù)
// 關(guān)閉程序回調(diào)
Runtime.getRuntime().addShutdownHook(new Thread(
() -> {
// 關(guān)閉netty
this.nettyClose();
running.shutdown();
}));
enum枚舉類案例
/**
* @author yuanfeng.z
* @description 市場數(shù)據(jù)請求類型
* @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 出現(xiàn)錯誤:找不到或無法加載主類 解決辦法
https://blog.csdn.net/angry_mills/article/details/81511130
https://blog.csdn.net/lizongbao1234567890/article/details/78120851
jvm參數(shù)
堆最小值:-Xms
堆最大值:-Xmx
每個線程棧大小:-Xss
方法區(qū)(靜態(tài)區(qū))最小值:-XX:PermSize
方法區(qū)(靜態(tài)區(qū))最大值:-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小數(shù)會有精度問題
BigDecimal b = new BigDecimal(0.000001);
BigDecimal比較大小,一定要用compareTo,不能用equals,因為比較0和0.0時不相等
BigDecimal.ZERO.compareTo(level.getBigDecimal(1)) == 0
double轉(zhuǎn)String,解決科學(xué)計數(shù)法問題
// bug:生成的idStr長度不一定一樣
final double size = 100000000000d;
double id = Math.floor(random.nextDouble() * size);
DecimalFormat df = new DecimalFormat("#");
String idStr = df.format(id);
指定double類型值小數(shù)位數(shù)
// 兩位
final double size = 100000000000d;
double id = Math.floor(random.nextDouble() * size);
DecimalFormat df = new DecimalFormat("#.##");
String idStr = df.format(id);
Quartz任務(wù)調(diào)度管理類
**
* @author yuanfeng.z
* @description 任務(wù)調(diào)度器
* @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組件關(guān)系
image.png - 任務(wù)管理器
/**
* @author yuanfeng.z
* @description 任務(wù)調(diào)度器
* @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加入調(diào)度器
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();
}
}
/**
* 定義觸發(fā)的條件
* @param second 觸發(fā)間隔(秒)
* @param name 觸發(fā)器名字
* @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;
}
/**
* 獲取任務(wù)調(diào)度實(shí)例
* @return
* @throws SchedulerException
*/
private static Scheduler getScheduler() throws SchedulerException {
StdSchedulerFactory sf =new StdSchedulerFactory();
Properties props = new Properties();
// 指定調(diào)度實(shí)例名字
props.put("org.quartz.scheduler.instanceName","orderScheduler");
// 指定調(diào)度實(shí)例線程數(shù)
props.put("org.quartz.threadPool.threadCount","20");
sf.initialize(props);
return sf.getScheduler();
}
}
- 創(chuàng)建job
/**
* 創(chuàng)建擺盤job實(shí)例
* @param markingEx
* @param refEx
* @param log
* @return
* @throws SchedulerException
*/
private JobDetail orderJob(Exchange markingEx, Exchange refEx, Logger log, Notice notice, String group) throws SchedulerException {
/**給定時任務(wù)傳遞參數(shù)*/
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);
/**任務(wù)*/
JobDetail job = newJob(OrderJob.class)
.withIdentity(markingEx.getSymbol(), group)
.usingJobData(jobDataMap)
.build();
return job;
}
- 實(shí)現(xiàn)job
/**
* @author yuanfeng.z
* @description 任務(wù)類
* @DisallowConcurrentExecution 等一個任務(wù)結(jié)束才會執(zhí)行下一個
* @date 2019/1/18 14:14
*/
// 禁止并發(fā)執(zhí)行多個相同定義的JobDetail
@DisallowConcurrentExecution
public class HedgingJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
/**獲取參數(shù)*/
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());
}
}
創(chuàng)建線程池工具類
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.線程設(shè)置異常捕獲
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();











