有人可以对报告的这个错误有所了解:
"main" prio=5 tid=1 WAIT
| group="main" sCount=1 dsCount=0 obj=0x40b97568 self=0x40b5ba68
| sysTid=29071 nice=0 sched=0/0 cgrp=apps handle=1074202160
| schedstat=( 2218977000 625819000 2260 ) utm=177 stm=44 core=0
at java.lang.Object.wait(Native Method)
- waiting on <0x412f4160> (a java.lang.VMThread) held by tid=12 (Thread-699)
at java.lang.Object.wait(Object.java:364)
at java.lang.Thread.join(Thread.java:761)
at com.pyesmeadow.pendulumclock.PendulumAppView.pause(PendulumAppView.java:419)
这似乎表明它正在等待一个 id 为 12 的线程。查看堆栈跟踪,我对线程 #12 有以下信息:
"Thread-699" prio=5 tid=12 NATIVE
| group="main" sCount=1 dsCount=0 obj=0x41715d38 self=0x678ba008
| sysTid=29098 nice=0 sched=0/0 cgrp=apps handle=1642643840
| schedstat=( 12528326000 501640000 3154 ) utm=1206 stm=46 core=0
#00 pc 0000dc70 /system/lib/libc.so (__futex_syscall3+8)
#01 pc 0001212c /system/lib/libc.so
#02 pc 0001a9cf /system/lib/libgui.so
#03 pc 00021351 /system/lib/libgui.so (android::SurfaceTextureClient::disconnect(int)+32)
#04 pc 000213c7 /system/lib/libgui.so (android::SurfaceTextureClient::~SurfaceTextureClient()+22)
#05 pc 00021445 /system/lib/libgui.so (android::SurfaceTextureClient::~SurfaceTextureClient()+4)
#06 pc 0000ee89 /system/lib/libutils.so (android::RefBase::decStrong(void const*) const+40)
#07 pc 000497db /system/lib/libandroid_runtime.so (android::sp<android::InputChannel>::~sp()+10)
#08 pc 000567e1 /system/lib/libandroid_runtime.so
#09 pc 0001de30 /system/lib/libdvm.so (dvmPlatformInvoke+112)
#10 pc 0004d083 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+394)
#11 pc 00027260 /system/lib/libdvm.so
#12 pc 0002bb68 /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180)
#13 pc 0005f7f1 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
#14 pc 0005f81b /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...)+20)
#15 pc 000543d3 /system/lib/libdvm.so
#16 pc 00012dd0 /system/lib/libc.so (__thread_entry+48)
#17 pc 00012528 /system/lib/libc.so (pthread_create+172)
at android.view.Surface.isValid(Native Method)
at com.pyesmeadow.pendulumclock.PendulumAppView$WorkerThread.run(PendulumAppView.java:169)
基本上,该线程负责更新 UI。它所指的代码行是调用isValid()
:
if( _surfaceHolder.getSurface().isValid() )
{
// ...
}
回到第一个堆栈转储(上图),问题似乎出现_workerThread.join()
在此代码中对(_workerThread 是 id 为 #12 的线程)的调用中:
public void pause()
{
_workerThread.setRunning( false );
// Wait for the background thread to terminate.
while( true )
{
try
{
_workerThread.join();
break;
}
catch( InterruptedException ex )
{
}
}
}
似乎通过调用join()
工作线程正在发生死锁,但我不知道为什么。
任何帮助,将不胜感激。
韦恩。
** * ***更新** * ** * ****
这是我run()
在工作线程中的方法的代码:
(请注意,在我的代码的生产版本中,_running\ 是一个非易失性布尔值)
public void setRunning( boolean flag )
{
_running = flag;
}
@Override
public void run()
{
int previousIndex = 0;
_timeSwingStarted = new Date();
while( _running )
{
if( _swingPath == null || _swingPath.isEmpty() )
continue;
if( Thread.interrupted() )
break;
if( _mode == PendulumMode.Swinging )
{
Date current = new Date();
long elapsed = current.getTime() - _timeSwingStarted.getTime();
int index = (int) Math.floor( ((double) Math.min(elapsed, 2000.0f) / 2000.0f) * (_swingPath.size() - 1) );
index = Math.max( Math.min( index, _swingPath.size() - 1), 0 );
if( index == previousIndex )
continue;
// Calculate the position of the pendulum and render it on the display
_currentPosition = _swingPath.get( index );
// only render the UI if there is a valid surface to render on
if( _surfaceHolder.getSurface().isValid() )
_theme.render( _currentPosition, _scrollOffsetY, _showFPS );
// Check whether the direction of the pendulum has changed
previousIndex = index;
if( index >= _swingPath.size() - 1 )
_timeSwingStarted = new Date();
}
//
// Check whether we should close the app automatically if a
// specified battery level has been reached.
//
if( _closeWhenBatteryLow && isBatteryLevelBelowThreshold() )
{
//
// Schedule a shutdown time and notify the user in case they wish
// to change their minds by adjusting the app settings.
//
if( _shutDownTime == null )
{
_shuttingDownReason = ShutdownReason.BatteryLow;
_shutDownTime = Calendar.getInstance();
_shutDownTime.add( Calendar.MINUTE, 2 );
((Activity) _context).runOnUiThread( new Runnable() {
public void run() {
showWarning( getResources().getString( R.string.batteryLowClosingMessage ) );
}
});
}
}
//
// Determine whether it's time to shutdown the app, if so the perform
// some extra checks to ensure that the user hasn't changed their minds
// since the initial message was displayed.
//
if( _shutDownTime != null )
{
Calendar now = Calendar.getInstance();
if( now.after( _shutDownTime ) )
{
if( _shuttingDownReason == ShutdownReason.BatteryLow )
{
if( _closeWhenBatteryLow && isBatteryLevelBelowThreshold() )
{
((Activity) _context).finish();
}
else
{
_shuttingDownReason = ShutdownReason.None;
_shutDownTime = null;
}
}
}
}
try
{
Thread.sleep( _sleepDuration );
}
catch( InterruptedException e )
{
/* at least we tried */
}
}
}