Skip to content

Commit b44bad2

Browse files
committed
多线程
1 parent 8ec5c6d commit b44bad2

13 files changed

Lines changed: 464 additions & 0 deletions

File tree

src/com/yale/test/java/demo/string/StringBufferDemo.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
/**
44
* String特点:任何的字符串常量都是String对象,而且String的常量一旦声明则不可改变, 如果改变对象的内容改变的是其引用的指向而已
5+
* 如果一个类被设计为允许多线程正确访问,我们就说这个类就是“线程安全”的(thread-safe),上面的Counter类就是线程安全的。Java标准库的java.lang.StringBuffer也是线程安全的。
6+
* 还有一些不变类,例如String,Integer,LocalDate,它们的所有成员变量都是final,多线程同时访问时只能读不能写,这些不变类也是线程安全的。
7+
* 最后,类似Math这些只提供静态方法,没有成员变量的类,也是线程安全的。
8+
* 除了上述几种少数情况,大部分类,例如ArrayList,都是非线程安全的类,我们不能在多线程中修改它们。但是,如果所有线程都只读取,不写入,那么ArrayList是可以安全地在线程间共享的。
9+
* 没有特殊说明时,一个类默认是非线程安全的。
510
* @author dell
611
*/
712
public class StringBufferDemo {

src/com/yale/test/java/fanshe/perfma/VolatileDemo.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@
4040
* 每次修改变量后,立刻回写到主内存。
4141
* volatile关键字解决的是可见性问题:当一个线程修改了某个共享变量的值,其他线程能够立刻看到修改后的值。
4242
* 如果我们去掉volatile关键字,运行上述程序,发现效果和带volatile差不多,这是因为在x86的架构下,JVM回写主内存的速度非常快,但是,换成ARM的架构,就会有显著的延迟。
43+
* x86架构加不加volatile其实区别不大,其他架构要注意,很可能一个线程改了值几秒内另一个线程读的还是旧的
4344
* https://www.liaoxuefeng.com/wiki/1252599548343744/1306580767211554
45+
* volatile只保证:
46+
* 读主内存到本地副本;
47+
* 操作本地副本;
48+
* 回写主内存。
49+
* 这3步多个线程可以同时进行。
4450
* @author dell
4551
*/
4652
public class VolatileDemo {

src/com/yale/test/java/fanshe/proxy/ProxyInvocationHandler.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public void eat(String msg, int num) {
2525
* 发展到现在用的比较多的是javasist来实现动态代理类,cglib用的也不太多了,主要用javasist
2626
* 静态代理只能代理一个接口下面的所有实现类,动态代理能代理所有接口的所有实现类
2727
* 代理的好处:使真实的类更纯净了(减轻了真实类的业务),不再关注一些公共的事情
28+
* 终于有人把 java 代理 讲清楚了,万字详解!https://xie.infoq.cn/article/9a9387805a496e1485dc8430f
2829
* @author dell
2930
*/
3031
class ProxySubjectSec implements InvocationHandler {//是一个动态代理类

src/com/yale/test/math/BigIntegerTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
如果是JDK8,推荐使用LongAdder对象,比AtomicLong性能更好(减少乐观锁的重试次数)。《阿里巴巴Java开发手册(泰山版).
1313
在Java中,由CPU原生提供的整型最大范围是64位long型整数。使用long型整数可以直接通过CPU指令进行计算,速度非常快。
1414
和long型整数运算比,BigInteger不会有范围限制,但缺点是速度比较慢。
15+
* 大端小端可以参考阮一峰写的文章[字符编码笔记:ASCII,Unicode 和 UTF-8]:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
16+
* 七、Little endian 和 Big endian
17+
* 上一节已经提到,UCS-2 格式可以存储 Unicode 码(码点不超过0xFFFF)。以汉字严为例,Unicode 码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,这就是 Big endian 方式;25在前,4E在后,这是 Little endian 方式。
18+
* 这两个古怪的名称来自英国作家斯威夫特的《格列佛游记》。在该书中,小人国里爆发了内战,战争起因是人们争论,吃鸡蛋时究竟是从大头(Big-endian)敲开还是从小头(Little-endian)敲开。为了这件事情,前后爆发了六次战争,一个皇帝送了命,另一个皇帝丢了王位。
19+
* 第一个字节在前,就是"大头方式"(Big endian),第二个字节在前就是"小头方式"(Little endian)。
20+
* 那么很自然的,就会出现一个问题:计算机怎么知道某一个文件到底采用哪一种方式编码?
21+
* Unicode 规范定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(zero width no-break space),用FEFF表示。这正好是两个字节,而且FF比FE大1。
22+
* 如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。
1523
* @author dell
1624
*/
1725
public class BigIntegerTest {

src/com/yale/test/ps/Base64Test.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package com.yale.test.ps;
22

3+
import java.io.IOException;
34
import java.io.UnsupportedEncodingException;
45
import java.net.URLDecoder;
56
import java.net.URLEncoder;
67
import java.util.Arrays;
78
import java.util.Base64;
89

10+
import sun.misc.BASE64Decoder;
11+
import sun.misc.BASE64Encoder;
12+
913
/*
1014
* 在计算机系统中,什么是加密与安全呢?
1115
* 我们举个栗子:假设Bob要给Alice发一封邮件,在邮件传送的过程中,黑客可能会窃取到邮件的内容,所以需要防窃听。黑客还可能会篡改邮件的内容,Alice必须有能力识别出邮件有没有被篡改。最后,黑客可能假冒Bob给Alice发邮件,Alice必须有能力识别出伪造的邮件。
@@ -29,6 +33,10 @@
2933
* 如果字符是A~Z,a~z,0~9以及-、_、.、*,则保持不变;
3034
* 如果是其他字符,先转换为UTF-8编码,然后对每个字节以%XX表示。
3135
* 例如:字符中的UTF-8编码是0xe4b8ad,因此,它的URL编码是%E4%B8%AD。URL编码总是大写。
36+
* ①BASE64 严格地说,属于编码格式,而非加密算法
37+
* Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息。
38+
* 例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。
39+
* 在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到
3240
*/
3341
public class Base64Test {
3442
public static void main(String[] args) {
@@ -123,5 +131,54 @@ public static void main(String[] args) {
123131

124132
byte [] pwArr = Base64.getDecoder().decode(pwStr);
125133
System.out.println("解密后的字符串:" + new String(pwArr));
134+
135+
/*
136+
* BASE64的加密解密是双向的,可以求反解.
137+
* BASE64Encoder和BASE64Decoder是非官方JDK实现类。虽然可以在JDK里能找到并使用,但是在API里查不到。
138+
* JRE 中 sun 和 com.sun 开头包的类都是未被文档化的,他们属于 java, javax 类库的基础,其中的实现大多数与底层平台有关,
139+
* 一般来说是不推荐使用的。 BASE64 严格地说,属于编码格式,而非加密算法 .主要就是BASE64Encoder、BASE64Decoder两个类,我们只需要知道使用对应的方法即可。
140+
* 另,BASE加密后产生的字节位数是8的倍数,如果不够位数以=符号填充
141+
* BASE64
142+
* 按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。
143+
* (The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)
144+
* 常见于邮件、http加密,截取http信息,你就会发现登录操作的用户名、密码字段通过BASE64加密的。
145+
* http://www.jfh.com/jfperiodical/article/818
146+
*/
147+
String str = "12345678";
148+
//加密
149+
String stsPs = new BASE64Encoder().encodeBuffer(str.getBytes());
150+
System.out.println("sun.misc.BASE64Encoder加密后的数据:" + stsPs);
151+
String stsPs2 = Base64Test.encryptBASE64(str.getBytes());
152+
System.out.println("sun.misc.BASE64Encoder加密后的数据::静态方法" + stsPs2);
153+
try {
154+
byte[] res = new BASE64Decoder().decodeBuffer(stsPs);
155+
String originStr = new String(res);
156+
System.out.println("sun.misc.BASE64Decoder解密后的数据:" + originStr);
157+
158+
byte[] res2 = Base64Test.decryptBASE64(stsPs2);
159+
String originSt2r = new String(res2);
160+
System.out.println("sun.misc.BASE64Decoder解密后的数据:静态方法" + originSt2r);
161+
} catch (IOException e) {
162+
e.printStackTrace();
163+
}
164+
}
165+
166+
/**
167+
* Base64加密
168+
* @param key
169+
* @return
170+
*/
171+
public static String encryptBASE64(byte[] key) {
172+
return new BASE64Encoder().encodeBuffer(key);
173+
}
174+
175+
/**
176+
* Base64解密
177+
* @param key
178+
* @return
179+
* @throws IOException
180+
*/
181+
public static byte[] decryptBASE64(String key) throws IOException {
182+
return new BASE64Decoder().decodeBuffer(key);
126183
}
127184
}

src/com/yale/test/ps/HashDemo.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.security.NoSuchAlgorithmException;
77

88
/*
9+
* MD5(Message Digest algorithm 5,信息摘要算法)
910
* 哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
1011
* 哈希算法最重要的特点就是:
1112
* 相同的输入一定得到相同的输出;
@@ -121,5 +122,31 @@ public static void main(String[] args) {
121122
e.printStackTrace();
122123
}
123124

125+
/*
126+
* MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。
127+
* 将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。广泛用于加密和解密技术,常用于文件校验。校验?不管文件多大,经过MD5后都能生成唯一的MD5值。
128+
* 好比现在的ISO校验,都是MD5校验。怎么用?当然是把ISO经过MD5后产生MD5的值。一般下载linux-ISO的朋友都见过下载链接旁边放着MD5的串。就是用来验证文件是否一致的。
129+
* 通常我们不直接使用上述MD5加密。通常将MD5产生的字节数组交给BASE64再加密一把,得到相应的字符串Digest:汇编
130+
* MD5算法具有以下特点:
131+
* 1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
132+
* 2、容易计算:从原数据计算出MD5值很容易。
133+
* 3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
134+
* 4、弱抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
135+
* 5、强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。
136+
* MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被”压缩”成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。除了MD5以外,其中比较有名的还有sha-1、RIPEMD以及Haval等。
137+
* http://www.jfh.com/jfperiodical/article/818
138+
*/
139+
String originStr = "简单加密8888888888888888888";
140+
System.out.println("=======加密前的数据:" + originStr);
141+
try {
142+
MessageDigest md = MessageDigest.getInstance("MD5");
143+
byte[] inputData = originStr.getBytes();
144+
md.update(inputData);
145+
BigInteger bigInteger = new BigInteger(md.digest());
146+
System.out.println("加密后的数据:" + bigInteger.toString(16));
147+
} catch (NoSuchAlgorithmException e) {
148+
e.printStackTrace();
149+
}
150+
124151
}
125152
}

src/com/yale/test/ps/Hmac.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
/*
1717
* Hmac算法
18+
* HMAC(Hash Message Authentication Code,散列消息鉴别码)
1819
* 在前面讲到哈希算法时,我们说,存储用户的哈希口令时,要加盐存储,目的就在于抵御彩虹表攻击。
1920
* 我们回顾一下哈希算法:digest = hash(input),正是因为相同的输入会产生相同的输出,我们加盐的目的就在于,使得输入有所变化:digest = hash(salt + input)
2021
* 这个salt可以看作是一个额外的“认证码”,同样的输入,不同的认证码,会产生不同的输出。因此,要验证输出的哈希,必须同时提供“认证码”。
@@ -27,6 +28,10 @@
2728
* Hmac输出和原有的哈希算法长度一致。
2829
* 可见,Hmac本质上就是把key混入摘要的算法。验证此哈希时,除了原始的输入数据,还要提供key。
2930
* 为了保证安全,我们不会自己指定key,而是通过Java标准库的KeyGenerator生成一个安全的随机的key。下面是使用HmacMD5的代码:
31+
*
32+
* HMAC(Hash Message Authentication Code,散列消息鉴别码,基于密钥的Hash算法的认证协议。消息鉴别码实现鉴别的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,
33+
* 用这个标识鉴别消息的完整性。使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。
34+
* http://www.jfh.com/jfperiodical/article/818
3035
*/
3136
public class Hmac {
3237
public static void main(String[] args) {

src/com/yale/test/ps/Hmac2.java

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.yale.test.ps;
2+
3+
import java.io.IOException;
4+
import java.io.UnsupportedEncodingException;
5+
import java.security.InvalidKeyException;
6+
import java.security.NoSuchAlgorithmException;
7+
8+
import javax.crypto.KeyGenerator;
9+
import javax.crypto.Mac;
10+
import javax.crypto.SecretKey;
11+
import javax.crypto.spec.SecretKeySpec;
12+
13+
/*
14+
* Hmac算法
15+
* HMAC(Hash Message Authentication Code,散列消息鉴别码),基于密钥的Hash算法的认证协议。消息鉴别码实现鉴别的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,
16+
* 用这个标识鉴别消息的完整性。使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。
17+
* http://www.jfh.com/jfperiodical/article/818
18+
*/
19+
public class Hmac2 {
20+
public static final String KEY_MAC = "HmacMD5";
21+
22+
public static void main(String[] args) {
23+
try {
24+
String str = "简单加密";
25+
//使用同一密钥:对数据进行加密:查看俩次加密的结果是否一样
26+
getResult1(str);
27+
getResult2(str);
28+
} catch (NoSuchAlgorithmException e) {
29+
e.printStackTrace();
30+
} catch (InvalidKeyException e) {
31+
e.printStackTrace();
32+
} catch (IllegalStateException e) {
33+
e.printStackTrace();
34+
} catch (UnsupportedEncodingException e) {
35+
e.printStackTrace();
36+
} catch (IOException e) {
37+
e.printStackTrace();
38+
}
39+
}
40+
41+
/*
42+
* 初始化HMAC密钥
43+
*/
44+
public static String initMacKey() throws NoSuchAlgorithmException {
45+
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
46+
SecretKey secretKey = keyGenerator.generateKey();
47+
return Base64Test.encryptBASE64(secretKey.getEncoded());
48+
}
49+
50+
/*
51+
* HMAC加密:主要方法
52+
*/
53+
public static String encryptHMAC(byte[] data, String key) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
54+
SecretKey secretKey = new SecretKeySpec(Base64Test.decryptBASE64(key), KEY_MAC);
55+
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
56+
mac.init(secretKey);
57+
return new String(mac.doFinal(data));
58+
}
59+
60+
public static String getResult1(String inputStr) throws NoSuchAlgorithmException, InvalidKeyException, IOException {
61+
String path = "";//Tools.getClassPath()
62+
String fileSource = path + "/file/HMAC_key.txt";
63+
System.out.println("==================加密前的数据:" + inputStr);
64+
byte[] inputdata = inputStr.getBytes();
65+
String key = Hmac2.initMacKey();//产生密钥
66+
System.out.println("Mac密钥:===" + key);
67+
//将密钥写入文件Tools.WriteMyFile(fileSource, key);
68+
69+
String result = Hmac2.encryptHMAC(inputdata, key);//加密
70+
System.out.println("HMAC加密后:======" + result);
71+
return result;
72+
}
73+
74+
public static String getResult2(String inputStr) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
75+
System.out.println("加密前的数据==========" + inputStr);
76+
String path = "";//Tools.getClassPath();
77+
String fileSource = path + "/file/HMAC_key.txt";
78+
String key = null;
79+
//将密钥从文件中读取
80+
key = ""; //Tools.ReadMyFile(fileSource)
81+
System.out.println("读取的密钥为:=================" + key);
82+
byte[] inputData = inputStr.getBytes();
83+
//对数据进行加密
84+
String result = Hmac2.encryptHMAC(inputData, key);
85+
System.out.println("HMAC加密后:===" + result);
86+
return result;
87+
}
88+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.yale.test.ps;
2+
3+
import java.io.UnsupportedEncodingException;
4+
import java.math.BigInteger;
5+
import java.security.MessageDigest;
6+
import java.security.NoSuchAlgorithmException;
7+
8+
/*
9+
* SHA
10+
* 安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。
11+
* 对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。该算法经过加密专家多年来的发展和改进已日益完善,并被广泛使用。该算法的思想是接收一段明文,
12+
* 然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。
13+
* 散列函数值可以说是对明文的一种“指纹”或是“摘要”所以对散列值的数字签名就可以视为对此明文的数字签名。
14+
* SHA(Secure Hash Algorithm,安全散列算法),数字签名等密码学应用中重要的工具,
15+
* 被广泛地应用于电子商务等信息安全领域。虽然,SHA与MD5通过碰撞法都被破解了,
16+
* 但是SHA仍然是公认的安全加密算法,较之MD5更为安全
17+
* SHA-1与MD5的比较
18+
* 因为二者均由MD4导出,SHA-1和MD5彼此很相似。相应的,他们的强度和其他特性也是相似,但还有以下几点不同:
19+
* l, 对强行攻击的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2^128数量级的操作,而对SHA-1则是2^160数量级的操作。这样,SHA-1对强行攻击有更大的强度。
20+
* 2, 对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
21+
* 3, 速度:在相同的硬件上,SHA-1的运行速度比MD5慢。
22+
* http://www.jfh.com/jfperiodical/article/818
23+
*/
24+
public class SHAHashDemo {
25+
public static void main(String[] args) {
26+
String originStr = "简单加密";
27+
System.out.println("加密前的数据:=================" + originStr);
28+
byte[] inputData = originStr.getBytes();
29+
try {
30+
MessageDigest md = MessageDigest.getInstance("SHA");
31+
md.update(inputData);
32+
BigInteger sha = new BigInteger(md.digest());
33+
System.out.println("SHA加密后的数据:" + sha.toString(32));
34+
} catch (NoSuchAlgorithmException e) {
35+
e.printStackTrace();
36+
}
37+
}
38+
}

src/com/yale/test/ps/SignDemo.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
/*
1515
* 签名算法
16+
* SHA(Secure Hash Algorithm,安全散列算法)
1617
* 我们使用非对称加密算法的时候,对于一个公钥-私钥对,通常是用公钥加密,私钥解密。
1718
* 如果使用私钥加密,公钥解密是否可行呢?实际上是完全可行的。
1819
* 不过我们再仔细想一想,私钥是保密的,而公钥是公开的,用私钥加密,那相当于所有人都可以用公钥解密。这个加密有什么意义?

0 commit comments

Comments
 (0)