Oracle has two products that implement Java Platform Standard Edition (Java SE) 8: Java SE Development Kit (JDK) 8 and Java SE Runtime Environment (JRE) 8. JDK 8 is a superset of JRE 8, and contains everything that is in JRE 8, plus tools such as the compilers and debuggers necessary for developing applets and applications. JRE 8 provides the libraries, the Java Virtual Machine (JVM), and other components to run applets and applications written in the Java programming language. Note that the JRE includes components not required […]
View Details并发队列的选择 Java的并发包提供了三个常用的并发队列实现,分别是:ArrayBlockingQueue、ConcurrentLinkedQueue 和 LinkedBlockingQueue 。 ArrayBlockingQueue是**初始容量固定**的阻塞队列,我们可以用来作为数据库模块成功竞拍的队列,比如有10个商品,那么我们就设定一个10大小的数组队列。 ConcurrentLinkedQueue使用的是CAS原语无锁队列实现,是一个异步队列,入队的速度很快,出队进行了加锁,性能稍慢。 LinkedBlockingQueue也是阻塞的队列,入队和出队都用了加锁,当队空的时候线程会暂时阻塞。 在请求预处理阶段,由于我们的系统入队需求要远大于出队需求,一般不会出现队空的情况,所以我们可以选择ConcurrentLinkedQueue来作为我们的请求队列实现 1. 请求接口的合理设计 一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口。 通常静态HTML等内容,是通过CDN的部署,一般压力不大,核心瓶颈实际上在后台请求接口上。这个后端接口,必须能够支持高并发请求,同时,非常重要的一点,必须尽可能“快”,在最短的时间里返回用户的请求结果。为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点。仍然直接面向MySQL之类的存储是不合适的,如果有这种复杂业务的需求,都建议采用异步写入。 当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以从页面中看到用户是否秒杀成功。但是,这种属于“偷懒”行为,同时给用户的体验也不好,容易被用户认为是“暗箱操作”。 高并发下的数据安全 我们知道在多线程写入同一个文件的时候,会存现“线程安全”的问题(多个线程同时运行同一段代码,如果每次运行结果和单线程运行的结果是一样的,结果和预期相同,就是线程安全的)。如果是MySQL数据库,可以使用它自带的锁机制很好的解决问题,但是,在大规模并发的场景中,是不推荐使用MySQL的。秒杀和抢购的场景中,还有另外一个问题,就是“超发”,如果在这方面控制不慎,会产生发送过多的情况。我们也曾经听说过,某些电商搞抢购活动,买家成功拍下后,商家却不承认订单有效,拒绝发货。这里的问题,也许并不一定是商家奸诈,而是系统技术层面存在超发风险导致的。 1. 超发的原因 假设某个抢购场景中,我们一共只有100个商品,在最后一刻,我们已经消耗了99个商品,仅剩最后一个。这个时候,系统发来多个并发请求,这批请求读取到的商品余量都是99个,然后都通过了这一个余量判断,最终导致超发。(同文章前面说的场景) 在上面的这个图中,就导致了并发用户B也“抢购成功”,多让一个人获得了商品。这种场景,在高并发的情况下非常容易出现。 2. 悲观锁思路 解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。 悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。 虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗尽,系统陷入异常。 3. FIFO队列思路 那好,那么我们稍微修改一下上面的场景,我们直接将请求放入队列中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,是不是有点强行将多线程变成单线程的感觉哈。 然后,我们现在解决了锁的问题,全部请求采用“先进先出”的队列方式来处理。那么新的问题来了,高并发的场景下,因为请求很多,很可能一瞬间将队列内存“撑爆”,然后系统又陷入到了异常状态。或者设计一个极大的内存队列,也是一种方案,但是,系统处理完一个队列内请求的速度根本无法和疯狂涌入队列中的数目相比。也就是说,队列内的请求会越积累越多,最终Web系统平均响应时候还是会大幅下降,系统还是陷入异常。 4. 乐观锁思路 这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。 有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。 from:https://my.oschina.net/momisabuilder/blog/2992962
View Details数据结构 队列 集合 链表、数组 字典、关联数组 栈 树 二叉树 完全二叉树 平衡二叉树 二叉查找树(BST) 红黑树 B,B+,B*树 LSM 树 BitSet 常用算法 排序、查找算法 选择排序 冒泡排序 插入排序 快速排序 归并排序 希尔排序 堆排序 计数排序 桶排序 基数排序 二分查找 Java 中的排序工具 布隆过滤器 字符串比较 KMP 算法 深度优先、广度优先 贪心算法 回溯算法 剪枝算法 动态规划 朴素贝叶斯 推荐算法 最小生成树算法 最短路径算法 并发 Java 并发 多线程 线程安全 一致性、事务 事务 ACID 特性 事务的隔离级别 MVCC 锁 Java中的锁和同步类 公平锁 & 非公平锁 悲观锁 乐观锁 & CAS ABA 问题 CopyOnWrite容器 RingBuffer 可重入锁 & 不可重入锁 互斥锁 & 共享锁 死锁 操作系统 计算机原理 CPU 多级缓存 进程 线程 协程 Linux 设计模式 设计模式的六大原则 23种常见设计模式 应用场景 单例模式 […]
View Details转载自:https://blog.csdn.net/iplayvs2008/article/details/41910835 java格式化时间到毫秒: SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss:SSS"); String formatStr =formatter.format(new Date(); 附录: java格式化字母表 Symbol Meaning Presentation Example G era designator Text AD y year Number 2009 M month in year Text & Number July & 07 d day in month Number 10 h hour in am/pm (1-12) Number 12 H hour in day (0-23) Number 0 m minute in hour Number 30 s second in minute Number 55 S millisecond Number 978 E day in week Text Tuesday D day in year Number 189 F day of […]
View Details随机数Int的生成 生成无边界的Int
1 2 3 4 5 6 7 8 |
@Test public void testRandom_generatingIntegerUnbounded() throws Exception { int intUnbounded = new Random().nextInt(); System.out.println(intUnbounded); } |
生成有边界的Int
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingIntegerBounded_withRange() throws Exception { int min = 1; int max = 10; int intBounded = min + ((int) (new Random().nextFloat() * (max - min))); System.out.println(intBounded); } |
包含1而不包含10 使用Apache Common Math来生成有边界的Int
1 2 3 4 5 6 7 8 9 |
@Test public void testRandom_generatingIntegerBounded_withApacheMath() throws Exception { int min = 1; int max = 10; int intBounded = new RandomDataGenerator().nextInt(min, max); System.out.println(intBounded); } |
包含1且包含10 使用Apache Common Lang的工具类来生成有边界的Int
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingIntegerBounded_withApacheLangInclusive() throws Exception { int min = 1; int max = 10; int intBounded = RandomUtils.nextInt(min, max); System.out.println(intBounded); } |
包含1而不包含10 使用TreadLocalRandom来生成有边界的Int
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingIntegerBounded_withThreadLocalRandom() throws Exception { int min = 1; int max = 10; int threadIntBound = ThreadLocalRandom.current().nextInt(min, max); System.out.println(threadIntBound); } |
包含1而不包含10 随机数Long的生成 生成无边界的Long
1 2 3 4 5 6 7 8 |
@Test public void testRandom_generatingLongUnbounded() throws Exception { long unboundedLong = new Random().nextLong(); System.out.println(unboundedLong); } |
因为Random类使用的种子是48bits,所以nextLong不能返回所有可能的long值,long是64bits。 生成有边界的Long
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingLongBounded_withRange() throws Exception { long min = 1; long max = 10; long rangeLong = min + (((long) (new Random().nextDouble() * (max - min)))); System.out.println(rangeLong); } |
以上只会生成1到10的long类型的随机数 使用Apache Commons Math来生成有边界的Long
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingLongBounded_withApacheMath() throws Exception { long min = 1; long max = 10; long rangeLong = new RandomDataGenerator().nextLong(min, max); System.out.println(rangeLong); } |
此方式主要使用的RandomDataGenerator类提供的生成随机数的方法 使用Apache Commons Lang的工具类来生成有边界的Long
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingLongBounded_withApacheLangInclusive() throws Exception { long min = 1; long max = 10; long longBounded = RandomUtils.nextLong(min, max); System.out.println(longBounded); } |
RandomUtils提供了对java.util.Random的补充 使用ThreadLocalRandom生成有边界的Long
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingLongBounded_withThreadLocalRandom() throws Exception { long min = 1; long max = 10; long threadLongBound = ThreadLocalRandom.current().nextLong(min, max); System.out.println(threadLongBound); } |
随机数Float的生成 生成0.0-1.0之间的Float随机数
1 2 3 4 5 6 7 8 |
@Test public void testRandom_generatingFloat0To1() throws Exception { float floatUnbounded = new Random().nextFloat(); System.out.println(floatUnbounded); } |
以上只会生成包含0.0而不包括1.0的float类型随机数 生成有边界的Float随机数
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingFloatBounded_withRange() throws Exception { float min = 1f; float max = 10f; float floatBounded = min + new Random().nextFloat() * (max - min); System.out.println(floatBounded); } |
使用Apache Common Math来生成有边界的Float随机数
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingFloatBounded_withApacheMath() throws Exception { float min = 1f; float max = 10f; float randomFloat = new RandomDataGenerator().getRandomGenerator().nextFloat(); float generatedFloat = min + randomFloat * (max - min); System.out.println(generatedFloat); } |
使用Apache Common Lang来生成有边界的Float随机数
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingFloatBounded_withApacheLang() throws Exception { float min = 1f; float max = 10f; float generatedFloat = RandomUtils.nextFloat(min, max); System.out.println(generatedFloat); } |
使用ThreadLocalRandom生成有边界的Float随机数 ThreadLocalRandom类没有提供 随机数Double的生成 生成0.0d-1.0d之间的Double随机数
1 2 3 4 5 6 7 8 |
@Test public void testRandom_generatingDouble0To1() throws Exception { double generatorDouble = new Random().nextDouble(); System.out.println(generatorDouble); } |
与Float相同,以上方法只会生成包含0.0d而不包含1.0d的随机数 生成带有边界的Double随机数
1 2 3 4 5 6 7 8 9 10 11 12 |
@Test public void testRandom_generatingDoubleBounded_withRange() throws Exception { double min = 1.0; double max = 10.0; double boundedDouble = min + new Random().nextDouble() * (max - min); System.out.println(boundedDouble); assertThat(boundedDouble, greaterThan(min)); assertThat(boundedDouble, lessThan(max)); } |
使用Apache Common Math来生成有边界的Double随机数
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Test public void testRandom_generatingDoubleBounded_withApacheMath() throws Exception { double min = 1.0; double max = 10.0; double boundedDouble = new RandomDataGenerator().getRandomGenerator().nextDouble(); double generatorDouble = min + boundedDouble * (max - min); System.out.println(generatorDouble); assertThat(generatorDouble, greaterThan(min)); assertThat(generatorDouble, lessThan(max)); } |
使用Apache Common Lang生成有边界的Double随机数
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingDoubleBounded_withApacheLang() throws Exception { double min = 1.0; double max = 10.0; double generatedDouble = RandomUtils.nextDouble(min, max); System.out.println(generatedDouble); } |
使用ThreadLocalRandom生成有边界的Double随机数
1 2 3 4 5 6 7 8 9 10 |
@Test public void testRandom_generatingDoubleBounded_withThreadLocalRandom() throws Exception { double min = 1.0; double max = 10.0; double generatedDouble = ThreadLocalRandom.current().nextDouble(min, max); System.out.println(generatedDouble); } |
JAVA中有多少可以实现随机数的类或方法? java.util.Random 这个类提供了生成Bytes、Int、Long、Float、Double、Boolean的随机数的方法 java.util.Math.random 方法提供了生成Double随机数的方法,这个方法的内部实现也是调用了java.util.Random的nextDouble方法,只不过它对多线程进行了更好的支持,在多个线程并发时会减少每个随机数生成器的竞争 第三方工具类,如Apache Common Lang库与Apache Common Math库中提供的随机数生成类,真正使用一行代码来实现复杂的随机数生成 java.util.concurrent.ThreadLocalRandom 专为多线程并发使用的随机数生成器,使用的方法为ThreadLocalRandom.current.nextInt(),此类是在JDK1.7中提供的,并且特别适合ForkJoinTask框架,而且在这个类中直接提供了生成有边界的随机数的操作,如public int nextInt(int origin, int bound),这样也可以一行代码来实现复杂的随机数生成了。 最后的总结为单线程中使用java.util.Random类,在多线程中使用java.util.concurrent.ThreadLocalRandom类。 […]
View Details
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 |
import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFormat; public class format { double f = 111231.5585; public void m1() { BigDecimal bg = new BigDecimal(f); double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); System.out.println(f1); } /** * DecimalFormat转换最简便 */ public void m2() { DecimalFormat df = new DecimalFormat("#.00"); System.out.println(df.format(f)); } /** * String.format打印最简便 */ public void m3() { System.out.println(String.format("%.2f", f)); } public void m4() { NumberFormat nf = NumberFormat.getNumberInstance(); nf.setMaximumFractionDigits(2); System.out.println(nf.format(f)); } public static void main(String[] args) { format f = new format(); f.m1(); f.m2(); f.m3(); f.m4(); } } |
from:https://www.cnblogs.com/chenrenshui/p/6128444.html
View Details
1 2 3 4 5 6 7 8 9 |
List<String> getMatchers(String regex, String source){ Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(source); List<String> list = new ArrayList<>(); while (matcher.find()) { list.add(matcher.group()); } return list; } |
from:https://blog.csdn.net/w305172521/article/details/75330661
View DetailsString -> int s="12345"; int i; 第一种方法:i=Integer.parseInt(s); 第二种方法:i=Integer.valueOf(s).intValue(); 这两种方法有什么区别呢?作用是不是一样的呢?是不是在任何下都能互换呢? int -> String int i=12345; String s=""; 第一种方法:s=i+""; 第二种方法:s=String.valueOf(i); 这两种方法有什么区别呢?作用是不是一样的呢?是不是在任何下都能互换呢? 以下是答案: 第一种方法:s=i+""; //会产生两个String对象 第二种方法:s=String.valueOf(i); //直接使用String类的静态方法,只产生一个对象 第一种方法:i=Integer.parseInt(s);//直接使用静态方法,不会产生多余的对象,但会抛出异常 第二种方法:i=Integer.valueOf(s).intValue();//Integer.valueOf(s) 相当于 new Integer(Integer.parseInt(s)),也会抛异常,但会多产生一个对象 ——————————————————————-- 1如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或 i = Integer.parseInt([String],[int radix]); 2). int i = Integer.valueOf(my_str).intValue(); 注: 字串转成 Double, Float, Long 的方法大同小异. 2 如何将整数 int 转换成字串 String ? A. 有叁种方法: 1.) String s = String.valueOf(i); 2.) String s = Integer.toString(i); 3.) String s = "" + i; 注: Double, Float, Long 转成字串的方法大同小异. JAVA数据类型转换 […]
View Details这里使用Random类的nextInt()方法来生成,生成[min,max]区间的随机整数公式: Random rand=new Random(); rand.nextInt(max- min+ 1) + min; 这里封装成方法了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/** * 求[Min,Max]区间之间的随机整数。 * @param Min 最小值 * @param Max 最大值 * @return 一个Min和Max之间的随机整数 */ public static int randomIntMinToMax(int Min, int Max) { //如果相等,直接返回,还生成个屁 if(Min==Max) { return Max; } //如果Min比Max大,交换两个的值,如果不交换下面nextInt()会出错 if(Min>Max) { Min^=Max; Max^=Min; Min^=Max; } Random rand=new Random();//nextInt()不是静态方法,不能直接用类名调用 return rand.nextInt(Max - Min + 1) + Min; } |
实例:
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 |
package random; import java.util.Random; public class GetRandom { public static void main(String[] args) { Random rand = new Random(); int Min = 0; int Max = 9; int[] count = new int[Max - Min + 1]; for (int i = 0; i < 10000; i++) { count[randomIntMinToMax(Min, Max)]++; } System.out.println(); char percentCh = '%'; for (int i = 0; i < count.length; i++) { double percent = 100 * (double) count[i] / 10000; System.out.printf("%d生成次数:%-4d,占百分比:%.2f%c\n", i, count[i], percent, percentCh); } } /** * 求[Min,Max]区间之间的随机整数。 * * @param Min * 最小值 * @param Max * 最大值 * @return 一个Min和Max之间的随机整数 */ public static int randomIntMinToMax(int Min, int Max) { // 如果相等,直接返回,还生成个屁 if (Min == Max) { return Max; } // 如果Min比Max大,交换两个的值,如果不交换下面nextInt()会出错 if (Min > Max) { Min ^= Max; Max ^= Min; Min ^= Max; } Random rand = new Random();// nextInt()不是静态方法,不能直接用类名调用 return rand.nextInt(Max - Min + 1) + Min; } } |
运行结果:
1 2 3 4 5 6 7 8 9 10 |
0生成次数:998 ,占百分比:9.98% 1生成次数:962 ,占百分比:9.62% 2生成次数:1005,占百分比:10.05% 3生成次数:1020,占百分比:10.20% 4生成次数:1020,占百分比:10.20% 5生成次数:997 ,占百分比:9.97% 6生成次数:966 ,占百分比:9.66% 7生成次数:1002,占百分比:10.02% 8生成次数:1006,占百分比:10.06% 9生成次数:1024,占百分比:10.24% |
from:https://blog.csdn.net/qq_21808961/article/details/80526231
View Details