【发布时间】:2015-06-12 03:03:45
【问题描述】:
我试图找出我手机的相机可以拍照的最快速度。我用来管理相机的对象(没有相机逻辑)如下所示:
public class PictureTaker {
private boolean mIsTakingPicture;
public void takePicture() {
mIsTakingPicture = true;
}
public boolean isTakingPicture() {
return mIsTakingPicture;
}
}
在我的活动中,我创建了一个新线程并向其发布一个可运行的线程,以便在用户点击按钮时开始循环和拍照。我再次点击按钮停止线程。
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class CameraTestActivity extends ActionBarActivity {
private HandlerThread mThread;
private Handler mThreadHandler;
private volatile boolean mTestingCameraSpeed;
private PictureTaker mPictureTaker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_test);
mThread = new HandlerThread("testThread");
mThread.start();
mThreadHandler = new Handler(mThread.getLooper());
mPictureTaker = new PictureTaker();
}
public void toggleDoingStuff(final View view) {
Button b = (Button)view;
if(mTestingCameraSpeed) {
mTestingCameraSpeed = false;
b.setText("Start camera");
} else {
mTestingCameraSpeed = true;
mThreadHandler.post(new Runnable() {
public void run() {
loopUntilStop();
}
});
b.setText("Stop camera");
}
}
private void loopUntilStop() {
for(;;) {
if(!mTestingCameraSpeed) break;
if(!mPictureTaker.isTakingPicture()) {
Log.d("CameraTestActivity", "Taking picture at time " + System.currentTimeMillis());
mPictureTaker.takePicture();
}
}
}
}
由于布尔值是原子的,我不介意错过更新,因此我没有将 loopUntilStop() 中的 mIsTestingCameraSpeed 检查包装在 synchronized 块中。 (编辑:正如 mttdbrd 和 Kevin Krumwiede 指出的那样,如果没有同步或使变量易变,线程可能看不到更改)。
无论如何,上面的代码阻塞了 UI 线程。但是,将takePicture() 更改为
public void takePicture() {
mIsTakingPicture = false;
}
不会阻止 UI,但是 mIsTakingPicture 设置不正确。为了防止阻塞并使用takePicture()的第一个版本,我不得不将isTakingPicture()更改为使用锁:
public boolean isTakingPicture() {
synchronized (this) {
return mIsTakingPicture;
}
}
当mIsTakingPicture 设置为true 而不是false 时,为什么不使用锁阻止UI?我检查了Java documentation on intrinsic locks and synchronization 并没有找到任何可以解释的东西。我也看过这些 SO 问题,但没有一个回答我的问题:
- Android :UI Thread Blocked
- Thread blocks my Android UI
- Thread blocking UI in android
- Android asynchronous post blocks UI thread
- Android UI Thread Block when calling AsynchTask.get()
- load textures into a thread blocks the mainUI in android
编辑: Here 是 ANR 的日志。前两行表明线程挂起等待锁,从第 216 行看,似乎测试线程确实在某个时间点获得了锁。从 thread_list.cc 的第 161 行开始,操作系统尝试获取两个不同的互斥锁,但我不确定它们是否与问题有关。
【问题讨论】:
标签: java android multithreading concurrency