Java Math.random()导致主线程假死(?)

先来看下下面这段测试代码

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class Run {  
  2.     public static void main(String[] args) throws InterruptedException {  
  3.         Thread2 b = new Thread2();  
  4.         b.setName("t1");  
  5.         b.start();  
  6.                 Thread.sleep(2000);  
  7.                 System.out.println("main finished");  
  8.     }  
  9. }  
  10.   
  11. class Thread1 extends Thread {  
  12.     @Override  
  13.     public void run() {  
  14.         for (int i = 0; i < Integer.MAX_VALUE; i++) {  
  15.             String newString = new String();  
  16.             Math.random();  
  17.         }  
  18.     }  
  19.   
  20. }  
  21.   
  22. class Thread2 extends Thread {  
  23.     @Override  
  24.     public void run() {  
  25.         try {  
  26.             Thread1 a = new Thread1();  
  27.             a.start();  
  28.             System.out.println("begin join " + Thread.currentThread().getName());  
  29.             a.join();  
  30.             System.out.println("end join");  
  31.         } catch (InterruptedException e) {  
  32.             e.printStackTrace();  
  33.         }  
  34.     }  
  35. }  
运行main函数后,正常来说一定会在2秒(main中sleep的时间)后输出下面的结果

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. begin join t1  
  2. main finished  
但是等了很久,只输出了begin join t1,而main函数迟迟没有结束


分析

在Thread1启动后,几乎所有的cpu时间片都花费在Math.random()这行上,而没有时间回到主线程

所以,解决方法是:让CPU除了生产随机数,再做点其他事情,让主线程得到机会运行

简单修改一下代码,原先new String没有传参数,JVM可能会认为是无效代码不做处理,这是-server模式下的一个优化,现在加了参数,JVM认为需要开辟内存,在这个过程中,CPU时间片被拆分,分给了主线程

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. String newString = new String("" + i);  
现在再次运行,发现可以正常输出main finished了,当然实际开发过程中,也可以使用其他方式去拆分CPU时间片


本案例基于JDK1.8u91 server模式

<think>好的,我现在要回答用户关于如何在Java中使用Math.random()的问题。首先,我需要确认自己对Math.random()的理解是否正确。Math.random()JavaMath类的一个静态方法,它返回一个介于0.0(包含)到1.0(不包含)之间的伪随机double值。用户可能想知道如何生成特定范围内的随机数,比如整数或者指定范围的数。 接下来,我应该分步骤说明如何使用这个方法。首先介绍基本用法,生成0.0到1.0之间的数。然后,可能需要生成更大范围的数,例如0到某个最大值,这时候可以乘以最大值。但要注意,Math.random()返回的是double,如果需要整数,需要进行类型转换。 然后,用户可能想生成特定区间的数,比如最小值到最大值之间的数。这时候的公式应该是Math.random() * (max - min) + min。例如,生成5到10之间的double,或者整数。对于整数,需要将结果转换为int,但需要注意这样会丢失小数部分,所以可能需要使用四舍五入或者向上取整等方法。 另外,生成整数时,常见的方法是使用(int)(Math.random() * range) + min,但要注意范围是否正确。例如,生成1到6的整数(模拟骰子),可以用(int)(Math.random() * 6) + 1,因为Math.random()生成的数包括0.0到0.999...,乘以6得到0到5.999...,取整后是0到5,加1得到1到6。 还需要提醒用户,虽然Math.random()在简单情况下足够,但对于更复杂的随机数需求,比如需要种子控制或者更高质量的随机数,应该使用java.util.Random类或者ThreadLocalRandom等。 可能用户会问为什么有时候生成的数不包含最大值,这时候需要解释Math.random()本身的定义是不包含1.0的,所以乘以最大值后不包含最大值。如果需要包含最大值,可能需要调整公式,比如在整数情况下,将范围加1,例如生成0到99的整数可以写成(int)(Math.random() * 100),因为0.0到0.999...乘以100得到0到99.999...,取整后是0到99。 另外,可能需要注意线程安全的问题,但Math.random()内部是使用一个静态的Random实例,可能会有竞争条件,所以在多线程环境下推荐使用ThreadLocalRandom.current().nextInt()等方法。 最后,我应该给出示例代码,展示不同情况下的使用方式,并解释每个步骤。然后,在相关问题中,可以询问其他随机数生成方法、种子概念、范围包含问题,以及线程安全的替代方案。</think><< 在Java中,`Math.random()` 用于生成一个范围在 `[0.0, 1.0)`(包含0.0,不包含1.0)的伪随机 `double` 值。以下是具体用法和常见场景: ### 1. 生成基本随机数 直接调用 `Math.random()` 会返回默认范围的随机值: ```java double randomValue = Math.random(); System.out.println("随机数: " + randomValue); // 输出示例:0.5488135023048164 ``` ### 2. 生成特定范围的整数 要生成一个介于 `[min, max)` 的整数(例如生成1到10的整数): ```java int min = 1; int max = 10; int randomInt = (int)(Math.random() * (max - min)) + min; System.out.println("1到9的整数: " + randomInt); // 输出示例:7 ``` ### 3. 生成包含最大值的整数 若需要包含最大值(如生成1到10的闭区间),需调整范围: ```java int randomIntInclusive = (int)(Math.random() * (max - min + 1)) + min; System.out.println("1到10的整数: " + randomIntInclusive); // 输出示例:10 ``` ### 4. 生成特定范围的浮点数 生成 `[min, max)` 的浮点数(如5.0到10.0): ```java double minDouble = 5.0; double maxDouble = 10.0; double randomDouble = Math.random() * (maxDouble - minDouble) + minDouble; System.out.println("5.0到10.0的浮点数: " + randomDouble); // 输出示例:7.8321 ``` ### 注意事项 - **原理**:`Math.random()` 内部使用 `java.util.Random` 的静态实例,可能因多线程竞争导致性能问题。高并发场景建议用 `ThreadLocalRandom`。 - **精度问题**:`Math.random()` 返回的 `double` 仅有53位随机性,可能不适用于加密等安全敏感场景。 ### 替代方案(更灵活) 使用 `java.util.Random` 类: ```java import java.util.Random; Random rand = new Random(); int randomInt = rand.nextInt(10); // 0-9的整数 int dice = rand.nextInt(6) + 1; // 1-6的骰子 ``` ### 完整示例代码 ```java public class RandomExample { public static void main(String[] args) { // 生成0.0到1.0的随机数 System.out.println("基础随机值: " + Math.random()); // 生成1到10的整数(包含10) int min = 1, max = 10; int randomInclusive = (int)(Math.random() * (max - min + 1)) + min; System.out.println("1到10的整数: " + randomInclusive); // 生成5.0到10.0的浮点数 double randomDouble = Math.random() * 5 + 5; System.out.println("5.0到10.0的浮点数: " + randomDouble); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值