BigDecimal多线程做除法异常
在使用Bigdecimal的除法的时候要在devide的时候直接将精度设置好,不要以为devide以后再跟一个setScale就万事大吉了,这样当我们遇到无限循环小数的结果集的时候一样会导致异常java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result的抛出,在多线程中会造成线程无限wait,程序加锁,完蛋.
错误示范
new BigDecimal(1).divide(new BigDecimal("3")).setScale(2, BigDecimal.ROUND_DOWN);
正确示范
new BigDecimal(1).divide(new BigDecimal("3"), 2, BigDecimal.ROUND_DOWN);
实验代码
java
public static void main(String[] args) {
ExecutorService executorService =
new ThreadPoolExecutor(3, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
/*
线程1:
1、在devide的时候直接指定精度,程序正常运行
* */
executorService.submit(new Runnable() {
@Override
public void run() {
Date date = new Date();
System.out.println(Thread.currentThread().getName() + date);
int i = 1;
while (i < 100000000) {
// 除设置精度,遇到无限循环会Math包来做精度处理,线程状态 running
new BigDecimal(1).divide(new BigDecimal("3"), 2, BigDecimal.ROUND_DOWN);
i++;
}
Date date1 = new Date();
System.out.println(Thread.currentThread().getName() + date1);
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*
线程2:
1、线程内运算 直接 devide ,后续对结果做setScale 会导致线程内异常抛出,且线程外捕获不到,线程直接wait
* */
try {
executorService.submit(new Runnable() {
@Override
public void run() {
Date date = new Date();
System.out.println(Thread.currentThread().getName() + date);
int i = 1;
while (i < 100000000) {
// 除不设置精度,遇到无限循环导致线程 wait 陷入全部等待。
new BigDecimal(1).divide(new BigDecimal("3")).setScale(2, BigDecimal.ROUND_DOWN);
i++;
}
Date date1 = new Date();
System.out.println(Thread.currentThread().getName() + date1);
}
});
} catch (Throwable throwable) {
System.out.println(throwable);
}
/*
线程3:
1、线程内运算 直接 devide ,后续对结果做setScale 会导致线程内异常抛出,在线程内将异常捕获,并继续相关操作
* */
executorService.submit(new Runnable() {
@Override
public void run() {
Date date = new Date();
System.out.println(Thread.currentThread().getName() + date);
int i = 1;
while (i < 10) {
// 1、除不设置精度,遇到无限循环导致线程 wait 陷入全部等待。如果此处线程内部不抓异常抛出会直接陷入
try {
new BigDecimal(1).divide(new BigDecimal("3")).setScale(2, BigDecimal.ROUND_DOWN);
} catch (Throwable throwable) {
System.out.println(throwable);
}
i++;
}
Date date1 = new Date();
System.out.println(Thread.currentThread().getName() + date1);
}
});
}
