相关疑难解决方法(0)

Java静态初始化程序是否安全?

我正在使用静态代码块来初始化我所拥有的注册表中的某些控制器.因此,我的问题是,我可以保证这个静态代码块只在首次加载类时才会被调用一次吗?我知道我无法保证何时会调用此代码块,我猜它是在Classloader首次加载它时.我意识到我可以在静态代码块中同步类,但我的猜测实际上这是怎么回事?

简单的代码示例是;

class FooRegistry {

    static {
        //this code must only ever be called once 
        addController(new FooControllerImpl());
    }

    private static void addController(IFooController controller) { 
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

或者我应该这样做;

class FooRegistry {

    static {
        synchronized(FooRegistry.class) {
            addController(new FooControllerImpl());
        }
    }

    private static void addController(IFooController controller) {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

java static multithreading synchronization static-initializer

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

JDK是否提供虚拟消费者?

我需要在代码块中使用流中的'n'项然后完成,实质上:

 public static <T> void eat(Stream<T> stream, int n) 
     // consume n items of the stream (and throw them away)
 }
Run Code Online (Sandbox Code Playgroud)

在我的情况下,我无法改变签名返回Stream<T>简单return stream.skip(n); 我必须实际丢弃流中的一些元素(不是简单的逻辑) - 为下游消费者做好准备,这不需要知道这是怎么发生的,甚至不知道发生了什么.

最简单的方法是使用limit(n),但我必须调用流终止方法来激活流,所以本质上我有:

public static <T> void skip(Stream<T> stream, int n) {
    stream.limit(n).forEach(t -> {});
}
Run Code Online (Sandbox Code Playgroud)

注意:此代码完全简化了实际代码,仅用于说明目的.实际上,限制将不起作用,因为存在围绕什么/如何消耗元素的逻辑.可以把它想象成从流中消费"header"元素,然后让消费者使用"body"元素.

这个问题是关于"无所事事"的lambda t -> {}.

在JDK中的某个地方是否有"无所事事"的消费者,比如"无所事事"功能Function.identity()

java consumer java-8 java-stream

24
推荐指数
3
解决办法
6238
查看次数

为什么在静态初始化器中使用并行流会导致不稳定的死锁

注意:这是不是重复,请仔细阅读题目сarefully /sf/users/241389361/报价:

真正的问题是为什么代码有时会起作用.即使没有lambdas,问题也会重现.这让我觉得可能存在JVM错误.

/sf/answers/3759645221/的评论中,我试图找出原因,为什么代码的行为从一个开始到另一个不同,并且该讨论的参与者给了我一些建议来创建一个单独的主题.

不要考虑以下源代码:

public class Test {
    static {
        System.out.println("static initializer: " + Thread.currentThread().getName());

        final long SUM = IntStream.range(0, 5)
                .parallel()
                .mapToObj(i -> {
                    System.out.println("map: " + Thread.currentThread().getName() + " " + i);
                    return i;
                })
                .sum();
    }

    public static void main(String[] args) {
        System.out.println("Finished");
    }
}
Run Code Online (Sandbox Code Playgroud)

有时(几乎总是)它会导致死锁.

输出示例:

static initializer: main
map: main 2
map: ForkJoinPool.commonPool-worker-3 4
map: ForkJoinPool.commonPool-worker-3 3
map: ForkJoinPool.commonPool-worker-2 0
Run Code Online (Sandbox Code Playgroud)

但有时它会成功完成(非常罕见):

static initializer: main
map: main 2
map: main …
Run Code Online (Sandbox Code Playgroud)

java concurrency deadlock jvm-hotspot static-initialization

18
推荐指数
1
解决办法
894
查看次数

如何在lambda迭代和正常循环之间做出决定?

自从他引入Java 8以来,我真的迷上了lambdas,并且尽可能地开始使用它们,主要是为了开始习惯它们.最常见的用法之一是当我们想要迭代并对一组对象进行操作时,在这种情况下我要么求助于forEach或者stream().我很少写旧for(T t : Ts)循环,我差点忘了for(int i = 0.....).

然而,我们前几天与我的主管讨论过这个问题,他告诉我,lambdas并不总是最好的选择,有时会阻碍性能.从我在这个新功能上看过的一个讲座中我感觉lambda迭代总是被编译器完全优化,并且(总是?)比裸迭代更好,但他不同意.这是真的?如果是,我如何区分每种方案中的最佳解决方案?

PS:我不是在谈论建议申请的案例parallelStream.显然那些会更快.

java iteration lambda jvm java-8

10
推荐指数
1
解决办法
1053
查看次数

带有lambda表达式的invokeAndWait在静态初始化程序中永远挂起

我使用invokeAndWait偶然发现了一个问题.下面的示例代码说明了该问题.任何人都可以详细说明发生了什么事吗?为什么lambda表达式挂起而匿名内部类和方法ref没有.

public class Test {
    // A normal (non-static) initializer does not have the problem
    static {
        try {
            System.out.println("initializer start");

            // --- Works
            System.out.println("\nanonymous inner-class: Print.print");
            EventQueue.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    Print.print();
                }
            });

            // --- Works
            System.out.println("\nmethod ref: Print.print");
            EventQueue.invokeAndWait(Print::print);

            // --- Hangs forever
            System.out.println("\nlambda: Print.print");
            EventQueue.invokeAndWait(() -> Print.print());

            System.out.println("\ninitializer end");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Test();
    }
}
Run Code Online (Sandbox Code Playgroud)

Print类:

public class Print {
    public …
Run Code Online (Sandbox Code Playgroud)

java lambda swing

5
推荐指数
1
解决办法
700
查看次数

为什么主线程没有唤醒?

代码如下,在Main方法中我调用静态方法:

\n
public class Main {\n    public static void main(String[] args) {\n        MyFactory.getSomething();\n        System.out.println("over"); \n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在静态方法中,让主线程等待,然后由demo线程唤醒。但是主线程没有唤醒,我不知道为什么。

\n
import java.util.concurrent.TimeUnit;\n\npublic class MyFactory {\n    private static Object lock = new Object();\n\n    static{\n        init();\n    }\n\n    private static void init(){\n        new Thread(()->{\n            try {\n                // make this thread run after main thread\n                TimeUnit.SECONDS.sleep(3);\n                System.out.println("task run...");\n                synchronized (lock){\n                    lock.notifyAll();  // notify main thread\n                }\n            } catch (InterruptedException e) {\n                throw new RuntimeException(e);\n            }\n        },"demo-thread").start();\n\n        synchronized (lock){\n            try {\n                System.out.println("waiting...");\n …
Run Code Online (Sandbox Code Playgroud)

java multithreading jvm classloader

5
推荐指数
1
解决办法
191
查看次数

如果我在并行流中使用lambda会发生死锁但是如果我使用匿名类而不会发生这种情况?

以下代码导致死锁(在我的电脑上):

public class Test {
    static {
        final int SUM = IntStream.range(0, 100)
                .parallel()
                .reduce((n, m) -> n + m)
                .getAsInt();
    }

    public static void main(String[] args) {
        System.out.println("Finished");
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我reduce用匿名类替换lambda参数,它不会导致死锁:

public class Test {
    static {
        final int SUM = IntStream.range(0, 100)
                .parallel()
                .reduce(new IntBinaryOperator() {
                    @Override
                    public int applyAsInt(int n, int m) {
                        return n + m;
                    }
                })
                .getAsInt();
    }

    public static void main(String[] args) {
        System.out.println("Finished");
    }
}
Run Code Online (Sandbox Code Playgroud)

你能解释一下这种情况吗?

PS

我发现代码(与以前有点不同):

public class …
Run Code Online (Sandbox Code Playgroud)

java deadlock initialization forkjoinpool java-stream

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

Why when I don't use the "lambda method reference" code style in static block will cause deadlock?

PS: Sorry for my poor english.I can't describe the problem clearly. :(

When I don't use the "lambda method reference" code style in the static block, like:

static{
map.keySet().parallelStream().forEach(e -> {
            System.out.println(e);
        });
}
Run Code Online (Sandbox Code Playgroud)

then the program running forever, never stop.

But when I change the code to

static{
map.keySet().parallelStream().forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)

然后该错误消失了。该程序可以立即完成。

请直接看一下代码,我已经尽力简化了代码。

public class BugSimulate {

    static {
        init();
    }

    private static void init() {
        Map<Integer, String> map = new HashMap<>();

        int i = 0;
        map.put(++i, "1");
        map.put(++i, "1"); …
Run Code Online (Sandbox Code Playgroud)

java lambda jvm jvm-crash java-8

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