Q10*_*ing 5 java multithreading jvm classloader
代码如下,在Main方法中我调用静态方法:
public class Main {\n public static void main(String[] args) {\n MyFactory.getSomething();\n System.out.println("over"); \n }\n}\nRun Code Online (Sandbox Code Playgroud)\n在静态方法中,让主线程等待,然后由demo线程唤醒。但是主线程没有唤醒,我不知道为什么。
\nimport 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 lock.wait(); // wait\n System.out.println("wake up");\n } catch (InterruptedException e) {\n throw new RuntimeException(e);\n }\n }\n }\n public static Object getSomething(){\n return null;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n输出如下:
\nwaiting...\nRun Code Online (Sandbox Code Playgroud)\n我的预期应该是这样的:
\nwaiting...\ntask run...\nwake up\nover\nRun Code Online (Sandbox Code Playgroud)\n这里是Github上的演示代码,您可以下载运行。
\n我的尝试:
\ntask run...我看到有人说可能是死锁导致了问题。我不这么认为。因为我们在输出中看不到信息。所以demo thread根本没有获得锁。
当我更改代码时MyFactory.java。(添加一个新线程来运行init方法)
由此
\nstatic{\n init();\n}\n\nRun Code Online (Sandbox Code Playgroud)\n对此。
\nstatic{\n new Thread(()->init()).start();\n}\nRun Code Online (Sandbox Code Playgroud)\n一切正常。程序不会阻塞。
\n这是我更改代码后的输出。
\nstatic{\n new Thread(()->init()).start();\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\n回到原来的问题“为什么主线程没有唤醒”\xef\xbc\x9f\n我认为JVM没有完全加载是
\nMyFactory.class由于主线程阻塞\xe3\x80\x82我不知道我的猜测是否正确是对的???
我不是 JVM 内部的专家,但我认为问题出在这里:
static {
init();
}
Run Code Online (Sandbox Code Playgroud)
我怀疑这会在 JVM 类加载器加载类时执行。然而,这个类加载永远不会完成,因为您阻塞了类加载器本身,因此程序其余部分的执行将永远不会恢复,因此另一个线程永远不会启动。
如果删除静态块并直接调用它:
public static void main(String[] args) {
// ...
MyFactory.init();
MyFactory.getSomething();
// ...
}
Run Code Online (Sandbox Code Playgroud)
您会看到它工作正常。
更多详情参见JLS 12.4.2
顺便说一句,睡眠并不是同步线程的好主意。