Я пытаюсь использовать двойную проверку блокировки, чтобы поддерживать массив биномиальных коэффициентов, но недавно я прочитал, что двойная проверка блокировки не работает.Эффективность чрезвычайно важна, поэтому использование volatile не является вариантом, если только оно не находится внутри условных выражений.Я не вижу способа использовать статический класс с одноэлементным объектом (это часть фреймворка, и я не знаю, для каких чисел людям понадобится использовать функцию, поэтому я не могу угадать, какой максимумбудет выбрано значение или будет ли функция использоваться вообще).Единственное, о чем я могу думать, это сделать все не статичным и настаивать на том, чтобы каждый поток, которому необходимо использовать этот метод, создавал экземпляр объекта Choose со своим собственным массивом.Кажется, в этом не должно быть необходимости.
public static final class Util{
/**
* Static array of nCr values
*/
public static long[][] nCr_arr;
/**
* Calculate binomial coefficient (n k)
*
* @param n
* n
* @param k
* k
* @return n choose k
*/
public static long nCr(int n, int k) {
if (k < 0)
throw new ArithmeticException("Cannot choose a negative number");
if (n < 0) {
if (k % 2 == 0)
return nCr(-n + k - 1, k);
else
return -nCr(-n + k - 1, k);
}
if (k > n)
return 0;
if (k > n / 2)
k = n - k;
if (nCr_arr == null) {
synchronized (Util.class) {
if (nCr_arr == null)
nCr_arr = new long[n + 1][];
}
}
if (nCr_arr.length <= n) {
synchronized (Util.class) {
if (nCr_arr.length <= n) {
long[][] newNCR = new long[n + 1][];
System.arraycopy(nCr_arr, 0, newNCR, 0, nCr_arr.length);
nCr_arr = newNCR;
}
}
}
if (nCr_arr[n] == null) {
synchronized (Util.class) {
if (nCr_arr[n] == null)
nCr_arr[n] = new long[k + 1];
}
}
if (nCr_arr[n].length <= k) {
synchronized (Util.class) {
if (nCr_arr[n].length <= k) {
long[] newNCR = new long[k + 1];
System.arraycopy(nCr_arr[n], 0, newNCR, 0,
nCr_arr[n].length);
nCr_arr[n] = newNCR;
}
}
}
if (nCr_arr[n][k] == 0) {
if (k == 0)
nCr_arr[n][k] = 1;
else
nCr_arr[n][k] = nCr(n, k - 1) * (n - (k - 1)) / k;
}
return nCr_arr[n][k];
}
}