标签: java-8

在嵌套的Java 8并行流动作中使用信号量可能是DEADLOCK.这是一个错误吗?

考虑以下情况:我们使用Java 8并行流来执行并行forEach循环,例如,

IntStream.range(0,20).parallel().forEach(i -> { /* work done here */})
Run Code Online (Sandbox Code Playgroud)

并行线程的数量由系统属性"java.util.concurrent.ForkJoinPool.common.parallelism"控制,通常等于处理器的数量.

现在假设我们想限制特定工作的并行执行次数 - 例如因为该部分是内存密集型而内存约束意味着并行执行的限制.

限制并行执行的一种明显而优雅的方法是使用信号量(这里建议),例如,下面的代码片段将并行执行的数量限制为5:

        final Semaphore concurrentExecutions = new Semaphore(5);
        IntStream.range(0,20).parallel().forEach(i -> {

            concurrentExecutions.acquireUninterruptibly();

            try {
                /* WORK DONE HERE */
            }
            finally {
                concurrentExecutions.release();
            }
        });
Run Code Online (Sandbox Code Playgroud)

这很好用!

但是:在worker(at /* WORK DONE HERE */)中使用任何其他并行流可能会导致死锁.

对我来说,这是一个意外的行为.

说明:由于Java流使用ForkJoin池,因此内部forEach正在分叉,并且连接似乎正在等待.但是,这种行为仍然是出乎意料的.请注意,如果设置"java.util.concurrent.ForkJoinPool.common.parallelism"为1 ,并行流甚至可以工作.

另请注意,如果存在内部并行forEach,则它可能不透明.

问题: 这种行为是否符合Java 8规范(在这种情况下,它意味着禁止在并行流工作者中使用信号量)或者这是一个错误?

为方便起见:下面是一个完整的测试用例.除了"true,true"之外,两个布尔值的任何组合都有效,这会导致死锁.

澄清:为了明确这一点,让我强调一个方面:acquire信号量不会发生死锁.请注意,代码包含

  1. 获得信号量
  2. 运行一些代码
  3. 释放信号量

如果该段代码使用另一个并行流,则死锁发生在2. 然后在OTHER流内发生死锁.因此,似乎不允许一起使用嵌套并行流和阻塞操作(如信号量)!

请注意,记录并行流使用ForkJoinPool并且ForkJoinPool和Semaphore属于同一个包 - java.util.concurrent(因此可以预期它们可以很好地互操作).

/*
 * (c) Copyright Christian P. Fries, …
Run Code Online (Sandbox Code Playgroud)

java parallel-processing concurrency java-8 java-stream

21
推荐指数
2
解决办法
5721
查看次数

为什么Java 8中的lambdas不允许对匿名类没有的成员变量进行前向引用?

以下类包含一个成员变量runnable,该变量使用匿名内部类的实例进行初始化.内部类引用相同的成员:

class Example {
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println(runnable);
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

只要在分配成员之前未执行该方法并且JLS允许这样的引用,这就不是问题.

理论上,成员变量的声明可以转换为lambda表达式,如下所示:

Runnable runnable = () -> System.out.println(runnable);
Run Code Online (Sandbox Code Playgroud)

根据我的理解,这在功能上等同于前面的示例,但它被javac 1.8.0_05以下错误消息拒绝:

Error:(2, 54) java: self-reference in initializer
Run Code Online (Sandbox Code Playgroud)

虽然这种说法是正确的,但我不明白为什么不允许这样做.这是故意不允许的,可能是因为lambda表达式被编译为不同的字节代码,如果它被允许会导致问题?或者刚被禁止,因为这些引用在匿名内部类中使用时已经存在问题?还是JLS作家无意中不允许这样做?或者它是一个错误javac

lambda javac java-8

21
推荐指数
1
解决办法
2600
查看次数

Java 8 Streams并尝试使用资源

我认为流API在这里使代码更容易阅读.我发现了一些很烦人的东西.的Stream接口(java.util.stream.Stream)延伸的AutoClosable接口(java.lang.AutoCloseable)

因此,如果要正确关闭流,则必须使用try with resources.

清单1.不太好,溪流没有关闭.

   public void noTryWithResource() {
    Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));

   @SuppressWarnings("resource") List<ImageView> collect = photos.stream()
            .map(photo -> new ImageView(new Image(String.valueOf(photo)))).collect(Collectors.<ImageView>toList());
}
Run Code Online (Sandbox Code Playgroud)

清单2.2个imbricated尝试:(

   public void tryWithResource() {
    Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));

    try (Stream<Integer> stream = photos.stream()) {
        try (Stream<ImageView> map = stream
                .map(photo -> new ImageView(new Image(String.valueOf(photo))))) {
            List<ImageView> collect = map.collect(Collectors.<ImageView>toList());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

清单3.当map返回流时,必须关闭stream()map() …

java eclipse java-8 java-stream

21
推荐指数
3
解决办法
2万
查看次数

带泛型的LambdaConversionException:JVM错误?

我有一些带有方法引用的代码,它可以很好地编译并在运行时失败.

例外是这样的:

Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class redacted.BasicEntity; not a subtype of implementation type interface redacted.HasImagesEntity
    at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233)
    at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
    at java.lang.invoke.CallSite.makeSite(CallSite.java:289)
Run Code Online (Sandbox Code Playgroud)

触发异常的类:

class ImageController<E extends BasicEntity & HasImagesEntity> {
    void doTheThing(E entity) {
        Set<String> filenames = entity.getImages().keySet().stream()
            .map(entity::filename)
            .collect(Collectors.toSet());
    }
}
Run Code Online (Sandbox Code Playgroud)

抛出异常试图解决entity::filename.filename()宣布在HasImagesEntity.据我所知,我得到了异常,因为E的删除是BasicEntity,JVM没有(不能?)考虑E上的其他界限.

当我将方法引用重写为一个普通的lambda时,一切都很好.对我来说,一个构造按预期工作并且它的语义等价物爆炸似乎真的很可疑.

这可能是在规范中吗?我正在努力寻找一种不会在编译器或运行时出现问题的方法,并且没有提出任何建议.

java generics lambda java-8

21
推荐指数
3
解决办法
2589
查看次数

流状态计算:累积总和

假设我有一个Java IntStream,是否可以将其转换为具有累积总和的IntStream?例如,以[4,2,6,...]开头的流应转换为[4,6,12,...].

更一般地说,应该如何实现有状态流操作?感觉这应该是可能的:

myIntStream.map(new Function<Integer, Integer> {
    int sum = 0; 
    Integer apply(Integer value){ 
        return sum += value; 
    }
);
Run Code Online (Sandbox Code Playgroud)

有明显的限制,这只适用于顺序流.但是,Stream.map明确需要无状态映射函数.我是否正确错过了Stream.statefulMap或Stream.cumulative操作,还是缺少Java流的重点?

比较一下Haskell,其中scanl1函数正好解决了这个例子:

scanl1 (+) [1 2 3 4] = [1 3 6 10]
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream

21
推荐指数
2
解决办法
5056
查看次数

Java lambda表达式,转换和比较器

我正在查看Map界面的Java源代码,并遇到了这一小段代码:

    /**
     * Returns a comparator that compares {@link Map.Entry} in natural order on value.
     *
     * <p>The returned comparator is serializable and throws {@link
     * NullPointerException} when comparing an entry with null values.
     *
     * @param <K> the type of the map keys
     * @param <V> the {@link Comparable} type of the map values
     * @return a comparator that compares {@link Map.Entry} in natural order on value.
     * @see Comparable
     * @since 1.8
     */
    public static <K, …
Run Code Online (Sandbox Code Playgroud)

java lambda casting java-8

21
推荐指数
3
解决办法
8949
查看次数

为什么在发出终端操作后没有Java close()流?

在阅读了https://www.airpair.com/java/posts/spring-streams-memory-efficiency之后,我很想从数据库中传出结果,但正如我与同事讨论的那样(cfr.评论他补充说文章),需要记住使用try-with-resources构造来避免任何内存泄漏.

  1. 为什么Java 8库不会在每次终端操作后自行关闭流(不必在try-with-resources中包装流实例化)?
  2. 如果适用,是否有任何将此功能添加到Java的计划,或者请求它是否有意义?

java java-8 java-stream

21
推荐指数
1
解决办法
2041
查看次数

如何使用Files.walk()...根据条件获取文件图表?

我有以下目录结构:

/path/to/stuff/org/foo/bar/
/path/to/stuff/org/foo/bar/1.2.3/
/path/to/stuff/org/foo/bar/1.2.3/myfile.ext
/path/to/stuff/org/foo/bar/1.2.4/
/path/to/stuff/org/foo/bar/1.2.4/myfile.ext
/path/to/stuff/org/foo/bar/blah/
/path/to/stuff/org/foo/bar/blah/2.1/
/path/to/stuff/org/foo/bar/blah/2.1/myfile.ext
/path/to/stuff/org/foo/bar/blah/2.2/
/path/to/stuff/org/foo/bar/blah/2.2/myfile.ext
Run Code Online (Sandbox Code Playgroud)

我想得到以下输出:

/path/to/stuff/org/foo/bar/
/path/to/stuff/org/foo/bar/blah/
Run Code Online (Sandbox Code Playgroud)

我有以下代码(下面),这是低效的,因为它打印出来:

/path/to/stuff/org/foo/bar/
/path/to/stuff/org/foo/bar/
/path/to/stuff/org/foo/bar/blah/
/path/to/stuff/org/foo/bar/blah/
Run Code Online (Sandbox Code Playgroud)

这是Java代码:

public class LocatorTest
{

    @Test
    public void testLocateDirectories()
            throws IOException
    {
        long startTime = System.currentTimeMillis();

        Files.walk(Paths.get("/path/to/stuff/"))
             .filter(Files::isDirectory)
             .forEach(Foo::printIfArtifactVersionDirectory);

        long endTime = System.currentTimeMillis();

        System.out.println("Executed in " + (endTime - startTime) + " ms.");
    }

    static class Foo
    {

        static void printIfArtifactVersionDirectory(Path path)
        {
            File f = path.toAbsolutePath().toFile();
            List<String> filePaths = Arrays.asList(f.list(new MyExtFilenameFilter()));

            if (!filePaths.isEmpty())
            {
                System.out.println(path.getParent());
            }
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

过滤器: …

java java-8

21
推荐指数
1
解决办法
4万
查看次数

如何使用Java 8/lambda执行嵌套的'if'语句?

我有以下代码,并希望使用lambda函数实现它只是为了好玩.可以使用基本的聚合操作吗?

List<Integer> result = new ArrayList<>();

for (int i = 1; i <= 10; i++) {
    if (10 % i == 0) {
        result.add(i);
        if (i != 5) {
            result.add(10 / i);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用lambda:

List<Integer> result = IntStream.rangeClosed(1, 10)
                                .boxed()
                                .filter(i -> 10 % i == 0)
                                // a map or forEach function here?
                                // .map(return 10 / i -> if i != 5)
                                .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

java lambda functional-programming nested-if java-8

21
推荐指数
2
解决办法
5万
查看次数

Java - 使用Condition和Lambda在Array中查找元素

简而言之,我有这个代码,我想使用条件和lambda获取数组的特定元素.代码将是这样的:

Preset[] presets = presetDALC.getList();
Preset preset = Arrays.stream(presets).select(x -> x.getName().equals("MyString"));
Run Code Online (Sandbox Code Playgroud)

但显然这不起作用.在C#中会有类似的东西,但在Java中,我该怎么做?

java arrays lambda java-8 java-stream

21
推荐指数
3
解决办法
6万
查看次数