我认为这不是一个简单的问题。我将简要介绍一下正在发生的事情。假设我们在文件 Byron.txt 中有一个数据源:
她走在美丽中,像
万里无云的星空和星空;
和所有最好的黑暗和光明
在她的容貌和她的眼睛里相遇:
如此柔和的温柔的光芒,
天堂拒绝艳丽的日子。
这段代码在 AsyncTask 中执行:
final ArrayList<Record> poem = new ArrayList<Record>();
final Object objectLock = new Object();
private Record rec = new Record();
@Override
protected Void doInBackground(Void... args) {
String line = null;
int i;
int last;
try {
process = Runtime.getRuntime().exec("cat Byron.txt");
bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()), 8192);
synchronized (objectLock) {
poem.clear();
last = i = poem.size() - 1;
}
while(line = bufferedReader.readLine()) != null) {
rec.setString(line);
synchronized (objectLock) {
last++;
poem.add(last, rec);
}
while(!bPause && i < last) {
i++;
publishProgress(poem.get(i));
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected synchronized void onProgressUpdate(Record... m) {
if(m.length > 0) {
mContext.mTable.appendRow(m[0]);
}
}
UI 中有一个 TableLayout ,每次我们得到一个新行时,我们都会向它添加一个新的 TableRow。这是我们在 UI 中看到的输出:
她走在美丽中,像
万里无云的星空和星空;
万里无云的地方和繁星点点的天空;
万里无云的地方和繁星点点的天空;
对那温柔的光
如此温柔 对那温柔的光芒如此温柔
然后我们进入调试器,看看为什么会这样。
有时synchronized (objectLock)
会跳过并继续循环。
没有发布,因为i
已经赶上了last
。
之后,该块被跳过的次数被执行
,但是原始行丢失并且当前行被添加到poem
几次
然后,所有新行都被发布,直到再次i
捕获last
。
所以你看到我遵循了代码,我可以解释发生了什么,这里的问题是:为什么跳过这个块?,为什么?
我预计同步块会停止,直到它可以被执行。
至少这是我如何理解synchronized (objectLock)
即使不使用wait()
和的功能notify()
我不假装在这里打开一个讨论(虽然如果你想我们可以在聊天区打开一个)
如果你发现代码中有问题,那么,回答问题让我知道。
笔记:
synchronized
之所以需要,是因为在应用程序的其他地方,用户可能希望通过电子邮件发送他到目前为止收到的行。- 用户可以暂停发布(
bpause
);这就是while
循环,只有在错误时才会i
遵循。last
bPause