我遇到了一个奇怪的情况,在静态初始化程序中使用带有lambda的并行流看似永远没有CPU利用率.这是代码:
class Deadlock {
static {
IntStream.range(0, 10000).parallel().map(i -> i).count();
System.out.println("done");
}
public static void main(final String[] args) {}
}
Run Code Online (Sandbox Code Playgroud)
这似乎是此行为的最小再现测试用例.如果我:
代码立即完成.谁能解释这种行为?这是一个错误还是这个意图?
我正在使用OpenJDK版本1.8.0_66-internal.
Java流体育运动都sorted和limit方法,它们分别返回流的分类版本,并只返回返回一个流的项目的指定数量的流.当这些操作连续应用时,例如:
stream.sorted().limit(qty).collect(Collectors.toList())
Run Code Online (Sandbox Code Playgroud)
排序是以对项目进行排序qty还是整个列表排序的方式执行的?换句话说,如果qty是固定的,这个操作是在O(n)吗?文档没有单独指定这些方法的性能或相互结合使用.
我问的原因是这些操作的明显必要实现是排序然后限制,花时间?(n * log(n)).但是这些操作可以一起执行,O(n * log(qty))智能流式框架可以在执行之前查看整个流以优化这种特殊情况.
我有可以对自己的类型执行操作的东西(比如上下文,数字):
interface Number<N> {
N add(N to);
}
class Int implements Number<Int> {
Int add(Int to) {...}
}
Run Code Online (Sandbox Code Playgroud)
和作用于某个上限的所有子类型的actor:
interface Actor<U> {
<E extends U> E act(Iterable<? extends E> items);
}
Run Code Online (Sandbox Code Playgroud)
我想创建一个在任何数字类型上多态化的actor:
class Sum implements Actor<Number> {
<N extends Number<N>> N act(Iterable<? extends N> items) {...}
}
Run Code Online (Sandbox Code Playgroud)
现在,显然这不起作用,因为Number并且Number<N>不一样.实际上,由于Number不将实现者的类型参数约束为其自己的类型,因此这样的actor无法工作.但是我一般不关心Numbers 操作- 我对我的功能只对某些类型的数字工作感到满意N extends Number<N>
作为替代方案,我可以声明:
interface Actor<E> {
E act(Iterable<? extends E> items);
}
class Sum<N extends Number<N>> implements Actor<N> {
N act(Iterable<? …Run Code Online (Sandbox Code Playgroud) 在交集类型中将方法引用应用于第二种类型时,我遇到了一个非常奇怪的问题.这是一个最小的测试用例:
class LambdaTest {
interface A {}
interface B {
B doIt();
}
static class AB implements A, B {
public B doIt() {
return this;
}
}
static <E extends A & B> void run(E e) {
Collections.singleton(e).stream().map(B::doIt);
}
public static void main(String[] args) {
run(new AB());
}
}
Run Code Online (Sandbox Code Playgroud)
此代码编译但run在运行时失败并出现错误:
java.lang.invoke.LambdaConversionException:无效的接收器类型接口LambdaTest $ A; 不是实现类型接口LambdaTest $ B的子类型
显式指定lambda的类型时甚至会发生此问题:
static <E extends A & B> void run(E e) {
final Function<E, B> doIt = B::doIt;
Collections.singleton(e).stream().map(doIt);
} …Run Code Online (Sandbox Code Playgroud) 这个问题关注ThreadLocalRandomOpenJDK版本1.8.0的实现.
ThreadLocalRandom提供每线程随机数生成器,没有Random强加的同步开销.最明显的实现(IMO)将是这样的,它似乎保持向后兼容性而没有太多复杂性:
public class ThreadLocalRandom extends Random {
private static final ThreadLocal<ThreadLocalRandom> tl =
ThreadLocal.withInitial(ThreadLocalRandom::new);
public static ThreadLocalRandom current() {
return tl.get();
}
// Random methods moved here without synchronization
// stream methods here
}
public class Random {
private ThreadLocalRandom delegate = new ThreadLocalRandom();
// methods synchronize and delegate for backward compatibility
}
Run Code Online (Sandbox Code Playgroud)
但是,实际的实现是完全不同的,非常奇怪:
ThreadLocalRandomRandom逐字复制一些方法,稍作修改; 当然,大部分代码都可以重用.Thread 存储种子和用于初始化`ThreadLocalRandom的探测变量,违反封装;ThreadLocalRandom使用Unsafe访问的变量Thread,我想是因为这两个类在不同的包却状态变量必须是私有的Thread- Unsafe是因为封装违反唯一必要的;ThreadLocalRandom将其下nextGaussian一个存储在静态ThreadLocal而不是实例变量 …我在 Postgres 9.3 数据库中有以下场景:
我想确保对于引用表 B 的表 C 的每一行,cba = ca 也就是说,如果 C 引用了 B,那么两行都应该指向表 A 中的同一行。
在这种情况下,是否有更好的方法来强制执行数据完整性?
postgresql database-design referential-integrity constraints foreign-keys
在Java中,我经常发现自己在条件的每个分支中分配多个最终变量,如下所示:
final _ x;
final _ y;
if (_) {
x = _;
y = _;
} else {
x = _;
y = _;
}
Run Code Online (Sandbox Code Playgroud)
在Scala中我知道可以使用该技术分配单个val:
val x = {
if (_) {
_;
} else {
_;
}
}
Run Code Online (Sandbox Code Playgroud)
实际上,可以修改上述方法以通过使块返回与变量模式匹配的元组来分配多个变量,例如:
{
if (_) {
_;
} else {
_;
}
} match { case (x, y) => _ }
Run Code Online (Sandbox Code Playgroud)
但我发现这种语法很尴尬.有没有更简单的方法,理想情况下类似于Java代码,做我想要的?
Streams和fork-join都提供了并行化访问数组的代码的功能.例如,Arrays.parallelSetAll主要通过以下行实现:
IntStream.range(0, array.length).parallel()
.forEach(i -> { array[i] = generator.applyAsLong(i); });
Run Code Online (Sandbox Code Playgroud)
另外,文档的RecursiveAction,叉-join框架的一部分,包含以下示例:
static class SortTask extends RecursiveAction {
final long[] array; final int lo, hi;
...
void merge(int lo, int mid, int hi) {
long[] buf = Arrays.copyOfRange(array, lo, mid);
for (int i = 0, j = lo, k = mid; i < buf.length; j++)
array[j] = (k == hi || buf[i] < array[k]) ?
buf[i++] : array[k++];
}
}
Run Code Online (Sandbox Code Playgroud)
最后,从数组创建的并行流以多个线程访问数组(代码太复杂,无法在此汇总).
所有这些示例似乎都是对数组进行读取或写入,而没有任何同步或其他内存障碍(据我所知).我们知道,完全临时的多线程数组访问是不安全的,因为不能保证读取反映另一个线程中的写入,除非读取和写入之间存在先发生关系.实际上,这些Atomic...Array类是专门为解决这个问题而创建的.但是,鉴于上面的每个例子都在标准库或其文档中,我认为它们是正确的.
在这些例子中,有人可以解释一下哪种机制可以保证阵列访问的安全性?
scalaz.std.MapInstances声明任何值为a的地图Semigroup本身就是a Monoid.由于Int是Semigroup,下面的代码工作:
def merge[K](maps : Iterator[Map[K, Int]]) : Map[K, Int] = maps.reduce(_ |+| _)
Run Code Online (Sandbox Code Playgroud)
但是,我很惊讶以下代码不起作用:
class Num(value : Int) extends Semigroup[Num] {
def append(x : Num, y : Num): Num = new Num(x.value + y.value)
}
def merge[K](maps : Iterator[Map[K, Num]]) : Map[K, Num] = maps.reduce(_ |+| _)
Run Code Online (Sandbox Code Playgroud)
任何人都可以向我解释为什么值为我的自定义Semigroup类的地图不被视为Monoids?
java ×6
java-8 ×4
java-stream ×2
scala ×2
arrays ×1
constraints ×1
deadlock ×1
foreign-keys ×1
fork-join ×1
generics ×1
lambda ×1
postgresql ×1
random ×1
scalaz ×1
sorting ×1