Mos*_*cho 9 java linux concurrency executor busy-waiting
我有以下简单的代码:
package main;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws InterruptedException {
new Main();
}
public Main() throws InterruptedException {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.schedule(new MyRunnable(), 10, TimeUnit.SECONDS);
System.out.println("Shutting down...");
executor.shutdown();
System.out.println("Awaiting termination...");
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
System.out.println("Main finished!");
}
private class MyRunnable implements Runnable {
public void run() {
System.out.println("Finished running!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
实际上,虽然我的真实代码比这更复杂,但我可以在这些方面隔离问题.代码基本上等待10秒运行runnable,然后通知主程序的结束.
但是,我注意到了10秒钟,我的核心之一用于100%.
如果我评论这一行:
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
Run Code Online (Sandbox Code Playgroud)
cpu核心也以100%使用,主程序也在Runnable之前完成.
如果我评论这一行:
executor.shutdown();
Run Code Online (Sandbox Code Playgroud)
cpu已正确使用但程序无法完成.
如果我评论前两行,则cpu正确使用但主程序无法完成.
executor.shutdown();
做某种忙碌的等待而不是仅仅禁用提交新任务?附加细节:
$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)
$ uname -a
Linux XPSG 2.6.32-5-686-bigmem #1 SMP Sun May 6 04:39:05 UTC 2012 i686 GNU/Linux
Run Code Online (Sandbox Code Playgroud)
PS:拜托,请不要让我使用CountDownLatch
也不是newSingleThreadScheduledExecutor
.这跟我问的问题无关.谢谢.
编辑:
这是java转储:
Full thread dump Java HotSpot(TM) Server VM (20.1-b02 mixed mode):
"pool-1-thread-1" prio=10 tid=0x08780c00 nid=0x32ee runnable [0x6fdcc000]
java.lang.Thread.State: RUNNABLE
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:943)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:662)
"Low Memory Detector" daemon prio=10 tid=0x0874dc00 nid=0x32ec runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=10 tid=0x0874c000 nid=0x32eb waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=10 tid=0x0874a000 nid=0x32ea waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=10 tid=0x08748800 nid=0x32e9 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=10 tid=0x0873a000 nid=0x32e8 in Object.wait() [0x70360000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x9e8f1150> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked <0x9e8f1150> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
"Reference Handler" daemon prio=10 tid=0x08735400 nid=0x32e7 in Object.wait() [0x703b1000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x9e8f1050> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
- locked <0x9e8f1050> (a java.lang.ref.Reference$Lock)
"main" prio=10 tid=0x086b5c00 nid=0x32e3 waiting on condition [0xb6927000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x9e958998> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2025)
at java.util.concurrent.ThreadPoolExecutor.awaitTermination(ThreadPoolExecutor.java:1253)
at main.Main.<init>(Main.java:19)
at main.Main.main(Main.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
"VM Thread" prio=10 tid=0x08731800 nid=0x32e6 runnable
"GC task thread#0 (ParallelGC)" prio=10 tid=0x086bd000 nid=0x32e4 runnable
"GC task thread#1 (ParallelGC)" prio=10 tid=0x086be400 nid=0x32e5 runnable
"VM Periodic Task Thread" prio=10 tid=0x0874fc00 nid=0x32ed waiting on condition
JNI global references: 931
Heap
PSYoungGen total 18752K, used 645K [0x9e8f0000, 0x9fdd0000, 0xb3790000)
eden space 16128K, 4% used [0x9e8f0000,0x9e991510,0x9f8b0000)
from space 2624K, 0% used [0x9fb40000,0x9fb40000,0x9fdd0000)
to space 2624K, 0% used [0x9f8b0000,0x9f8b0000,0x9fb40000)
PSOldGen total 42880K, used 0K [0x74b90000, 0x77570000, 0x9e8f0000)
object space 42880K, 0% used [0x74b90000,0x74b90000,0x77570000)
PSPermGen total 16384K, used 2216K [0x70b90000, 0x71b90000, 0x74b90000)
object space 16384K, 13% used [0x70b90000,0x70dba198,0x71b90000)
Run Code Online (Sandbox Code Playgroud)
事实上,它正忙于等待。ThreadPoolExecutor 似乎没有退避逻辑来等待所有任务完成(请注意,这仅在您完成时才会发生shutdown()
,否则它将正确挂起线程)。
它不断检查任务是否准备好执行,如果没有,它将重试,直到调度任务的时间过去。
关闭计划线程池需要进行权衡(这种权衡是由实现强加的)。它会忙于旋转,直到任务准备好调度或shutdownNow
不会执行任何排队的任务。但是,您可以获取返回的 Runnable 列表并自己执行它们。
归档时间: |
|
查看次数: |
4170 次 |
最近记录: |