标签: java-8

通过Collections.synchronizedSet(...).forEach()的迭代是否保证是线程安全的?

我们知道,默认情况下迭代并发集合不是线程安全的,所以不能使用:

Set<E> set = Collections.synchronizedSet(new HashSet<>());
//fill with data
for (E e : set) {
    process(e);
}
Run Code Online (Sandbox Code Playgroud)

这是因为在迭代期间可能会添加数据,因为没有排他锁set.

这在javadoc中描述Collections.synchronizedSet:

public static Set synchronizedSet(Set s)

返回由指定集支持的同步(线程安全)集.为了保证串行访问,必须通过返回的集完成对后备集的所有访问.

当迭代它时,用户必须手动同步返回的集合:

Set s = Collections.synchronizedSet(new HashSet());
...
synchronized (s) { Iterator i = s.iterator(); // Must be in the synchronized block while (i.hasNext()) foo(i.next()); }

不遵循此建议可能会导致非确定性行为.

然而,这并不适用于Set.forEach,它继承了默认的方法forEachIterable.forEach.

现在我查看了源代码,在这里我们可以看到我们有以下结构:

  1. 我们要求一个Collections.synchronizedSet().
  2. 我们得到一个:

    public static <T> Set<T> synchronizedSet(Set<T> s) {
        return new SynchronizedSet<>(s); …
    Run Code Online (Sandbox Code Playgroud)

java collections thread-safety java-8

27
推荐指数
2
解决办法
4460
查看次数

Java 8 CompletableFuture中的默认值超时

假设我有一些异步计算,例如:

CompletableFuture
        .supplyAsync(() -> createFoo())
        .thenAccept(foo -> doStuffWithFoo(foo));
Run Code Online (Sandbox Code Playgroud)

如果异步供应商根据某些指定的超时超时,是否有一种很好的方法为foo提供默认值?理想情况下,此类功能也会尝试取消运行缓慢的供应商.例如,是否存在类似于以下假设代码的标准库功能:

CompletableFuture
        .supplyAsync(() -> createFoo())
        .acceptEither(
                CompletableFuture.completedAfter(50, TimeUnit.MILLISECONDS, DEFAULT_FOO),
                foo -> doStuffWithFoo(foo));
Run Code Online (Sandbox Code Playgroud)

或者甚至更好:

CompletableFuture
        .supplyAsync(() -> createFoo())
        .withDefault(DEFAULT_FOO, 50, TimeUnit.MILLISECONDS)
        .thenAccept(foo -> doStuffWithFoo(foo));
Run Code Online (Sandbox Code Playgroud)

我知道get(timeout, unit),但我想知道是否有一种更好的标准方式,以异步和反应方式应用超时,如上面的代码所示.

编辑:这是一个受Java 8启发的解决方案:在lambda表达式中强制检查异常处理.为什么强制,不是可选的?,但不幸的是它阻止了一个线程.如果我们依赖createFoo()来异步检查超时并抛出自己的超时异常,它可以在不阻塞线程的情况下工作,但会给供应商的创建者带来更多负担,并且仍然会产生创建异常的成本(可以没有"快速投掷"而昂贵

static <T> Supplier<T> wrapped(Callable<T> callable) {
    return () -> {
        try {
            return callable.call();
        } catch (RuntimeException e1) {
            throw e1;
        } catch (Throwable e2) {
            throw new RuntimeException(e2);
        }
    };
}
CompletableFuture
        .supplyAsync(wrapped(() -> CompletableFuture.supplyAsync(() -> createFoo()).get(50, …
Run Code Online (Sandbox Code Playgroud)

java java-8

27
推荐指数
4
解决办法
2万
查看次数

同步局部变量

我注意到一个奇怪的结构ConcurrentHashMapcomputecomputeIfAbsent方法:

Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
  //...
}
Run Code Online (Sandbox Code Playgroud)

考虑到JIT最有可能将其视为无操作,本地对象同步的重点是什么?

java multithreading synchronized concurrenthashmap java-8

27
推荐指数
1
解决办法
1713
查看次数

Java8 Streams - 删除具有Stream Distinct的重复项

我有一个流如:

Arrays.stream(new String[]{"matt", "jason", "michael"});
Run Code Online (Sandbox Code Playgroud)

我想删除以相同字母开头的名称,以便只留下以该字母开头的一个名称(无关紧要).

我试图了解该distinct()方法的工作原理.我在文档中读到它基于对象的"等于"方法.但是,当我尝试包装String时,我注意到从不调用equals方法,也没有删除任何内容.这里有什么我想念的吗?

包装类:

static class Wrp {
    String test;
    Wrp(String s){
        this.test = s;
    }
    @Override
    public boolean equals(Object other){
        return this.test.charAt(0) == ((Wrp) other).test.charAt(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一些简单的代码:

public static void main(String[] args) {
    Arrays.stream(new String[]{"matt", "jason", "michael"})
    .map(Wrp::new)
    .distinct()
    .map(wrp -> wrp.test)
    .forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)

java string java-8 java-stream

27
推荐指数
2
解决办法
6万
查看次数

我如何否定lambda谓词?

假设我有一串字符串.

final Stream<String> stream = ...;
Run Code Online (Sandbox Code Playgroud)

我想在修剪后过滤掉每个空字符串.

stream
    .filter(Objects::nonNull)
    .map(String::trim)
    .filter(v -> !v.isEmpty());
Run Code Online (Sandbox Code Playgroud)

有没有办法应用Predicate#negate()替换v -> !v.isEmpty()部分?

.filter(((Predicate) String::isEmpty).negate()) // not compile
Run Code Online (Sandbox Code Playgroud)

java lambda predicate java-8

27
推荐指数
2
解决办法
1万
查看次数

Stream.collect方法中的组合器如何在java 8中工作?

我创建了简单的演示:

public static void main(String[] args) {
        List<String> list2 = Arrays.asList("adf", "bcd", "abc", "hgr", "jyt", "edr", "biu");

String collect = list2.stream().collect(String::new, (res, elem) -> {
              res=res.concat(" ").concat(elem);
//            System.out.printf("res=%s, elem=%s\n", res.isEmpty(), elem);

        }, (res1, res2) -> {
            System.out.printf("res1=%s, res2=%s\n", res1, res2);            
        });
        System.out.println("collect=" + collect);
}
Run Code Online (Sandbox Code Playgroud)

问题是BiConsumer combiner部分collect根本没有运行.

如果我使用parallelStream()两个参数res1并且res2等于供应商,它就会运行String::new.

如何combinercollect方法中工作?

java java-8 java-stream

27
推荐指数
3
解决办法
6385
查看次数

注册流"完成"钩子

使用Java 8 StreamAPI,我想注册一个"完成钩子",类似于:

Stream<String> stream = Stream.of("a", "b", "c");

// additional filters / mappings that I don't control
stream.onComplete((Completion c) -> {
    // This is what I'd like to do:
    closeResources();

    // This might also be useful:
    Optional<Throwable> exception = c.exception();
    exception.ifPresent(e -> throw new ExceptionWrapper(e));
});
Run Code Online (Sandbox Code Playgroud)

我为什么要那么做的原因是因为我想包装在一个资源Stream的API客户端,消费,我想的是Stream,一旦它被消耗自动清理资源.如果可能,那么客户可以致电:

Collected collectedInOneGo =
Utility.something()
       .niceLookingSQLDSL()
       .moreDSLFeatures()
       .stream()
       .filter(a -> true)
       .map(c -> c)
       .collect(collector);
Run Code Online (Sandbox Code Playgroud)

而不是目前所需要的:

try (Stream<X> meh = Utility.something()
                            .niceLookingSQLDSL()
                            .moreDSLFeatures()
                            .stream()) {

    Collected collectedWithUglySyntacticDissonance = …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream

27
推荐指数
3
解决办法
1967
查看次数

Java 8 Update 71正在尝试安装新的帮助工具.(在Mac上)

我刚刚被提示更新Java.它告诉我:

在此输入图像描述

有人知道那个"助手"工具是做什么的吗?如果它是新的我可能不需要它.有没有办法选择退出?或者至少在安装之前知道它是什么?

请注意,我已经在"系统偏好设置"下的"Java控制面板"中选中了禁止赞助商优惠的选项.

在此输入图像描述

另请注意,如果我未输入管理员密码,则不会安装更新.除了更新之外,它不是提供的,我可以接受或拒绝.

如果这是一个不好的问题或错误的地方,请评论.


这是一个后续行动.

我再次收到消息,并搜索了有关它的更多信息.我了解到更新过程已经包含在应用程序中.应用程序包装实际包,并提出其他软件.如果您选择退出,我猜它只是安装了Java更新.

"新助手工具"可能就是这个安装包装器,或者如果您不选择退出,可能还会提供其他软件.

如果您更喜欢安装干净的软件包,可以从安装程序中提取它.下载更新后,单击取消.然后转到~/Library/Application Support/Java(~/Library隐藏,所以使用Go> Go to folder ...).您可以看到所有过去的Java更新下载.选择最新版本.在文件夹中,您会看到一个应用程序和一个dmg.右键单击应用程序并选择Show Package Contents.在应用程序里面去Contents/Resources.你找到一个包裹JavaAppletPlugin.pkg.那是实际的包裹.双击它进行安装.它仍会询问您的姓名和密码,但这次是由OSX/macOS询问并用于安装该软件包而不是其他任何内容.


最新更新:今天更新失败.发生这种情况时,立即删除下载.在这种情况下,上述方法不起作用.


这开始看起来像博客.失败的下载是由于我的杀毒软件.当我禁用它时,它再次起作用.无论如何,我现在相信这个信息是无害的.操作系统X询问我是否同意运行Java安装程序.它不会尝试安装任何其他东西.我跑了.

java install auto-update java-8

27
推荐指数
1
解决办法
2万
查看次数

Java 8是否已缓存对供应商的支持?

guava库有它自己的Supplier,不扩展Java 8 Supplier.番石榴还为供应商提供缓存 - Suppliers#memoize.

是否有类似的东西,但对于Java 8供应商?

java guava java-8

27
推荐指数
3
解决办法
1万
查看次数

在Java 11中使用堆栈跟踪的速度明显慢于Java 8

当我遇到一些令人惊讶的数字时,我正在使用jmh 1.21 比较JDK 8和11的性能:

Java version: 1.8.0_192, vendor: Oracle Corporation

Benchmark                              Mode  Cnt      Score    Error  Units
MyBenchmark.throwAndConsumeStacktrace  avgt   25  21525.584 ± 58.957  ns/op


Java version: 9.0.4, vendor: Oracle Corporation

Benchmark                              Mode  Cnt      Score     Error  Units
MyBenchmark.throwAndConsumeStacktrace  avgt   25  28243.899 ± 498.173  ns/op


Java version: 10.0.2, vendor: Oracle Corporation

Benchmark                              Mode  Cnt      Score     Error  Units
MyBenchmark.throwAndConsumeStacktrace  avgt   25  28499.736 ± 215.837  ns/op


Java version: 11.0.1, vendor: Oracle Corporation

Benchmark                              Mode  Cnt      Score      Error  Units
MyBenchmark.throwAndConsumeStacktrace  avgt   25  48535.766 ± 2175.753 …
Run Code Online (Sandbox Code Playgroud)

performance java-8 jmh java-11

27
推荐指数
2
解决办法
2251
查看次数