ConcurrentModificationException即使在使用synchronized时也是如此(ConcurrentModificationException even when using synchronized)
我有两个线程:第一个是渲染线程,第二个线程是我处理UI操作的主线程。
我收到以下错误:
java.util.ConcurrentModificationException at java.util.AbstractList$SimpleListIterator.next(AbstractList.java:95) at com.convekta.android.chessboard.ChessBoard.renderGamerPieces(ChessBoard.java:424) at com.convekta.android.chessboard.ChessBoard.render(ChessBoard.java:162) at com.convekta.android.chessboard.ChessDrawThread.run(ChessDrawThread.java:41)
ConcurrentModification异常的常见原因是迭代列表的更改,但我只在
renderGamerPieces
函数中读取它。mGamerPieces
可能改变的唯一地方是loadPosition
方法,但loadPosition
和renderGamerPieces
都在synchronized块内调用也许我不明白的东西..那么这个错误可能会出现怎么样?
我的代码:
private final List<DrawablePiece> mGamerPieces = new ArrayList<DrawablePiece>(); private final Object mGamerPiecesLock = new Object(); public void loadPosition(byte[] pieces, byte[] places) { synchronized (mGamerPiecesLock) { mPicked = null; mGamerPieces.clear(); for (int i = 0; i < pieces.length; i++) { byte p = GamerUtils.UncastleRook(pieces[i]); if (p != GamerPieces.EMPTY) { byte pl = places[i]; if (pl <= GAME_BOARDSIZE) mGamerPieces.add(new DrawablePiece(p, GamerUtils.columnByCell(pl), GamerUtils.rowByCell(pl, true))); } } } } public void renderGamerPieces(Canvas canvas) { ... Rect r = new Rect(0, 0, mCellSize, mCellSize); List<DrawablePiece> over = new ArrayList<DrawablePiece>(); for (DrawablePiece d : mGamerPieces) { if (d.isFloating()) { over.add(d); } else { r.offsetTo(invert(d.getBoardCol()) * mCellSize, invert(d.getBoardRow()) * mCellSize); r.offset(mBoardRegion.left, mBoardRegion.top); Bitmap pic = mPieceFactory.getBitmapPiece(d.getPiece(), mCellSize); if (null != pic) canvas.drawBitmap(pic, null, r, null); } } ... } public void render(Canvas canvas) { ... synchronized (mGamerPiecesLock) { renderGamerPieces(canvas); } ... }
谢谢你的评论! 我将整理我的代码 - 在
renderGamerPieces
添加同步块,并检查可以从另一个同步块调用loadPosition
。I have two threads: first one is an render thread, the second thread is the main thread in which I handle UI actions.
I get the following error:
java.util.ConcurrentModificationException at java.util.AbstractList$SimpleListIterator.next(AbstractList.java:95) at com.convekta.android.chessboard.ChessBoard.renderGamerPieces(ChessBoard.java:424) at com.convekta.android.chessboard.ChessBoard.render(ChessBoard.java:162) at com.convekta.android.chessboard.ChessDrawThread.run(ChessDrawThread.java:41)
The usual reason of ConcurrentModification exception is changing of iterated list, but I only read it in
renderGamerPieces
function. The only place wheremGamerPieces
may change isloadPosition
method, but bothloadPosition
andrenderGamerPieces
are called inside synchronized blocksMaybe I didn't understand something.. So how this error may appear?
My code:
private final List<DrawablePiece> mGamerPieces = new ArrayList<DrawablePiece>(); private final Object mGamerPiecesLock = new Object(); public void loadPosition(byte[] pieces, byte[] places) { synchronized (mGamerPiecesLock) { mPicked = null; mGamerPieces.clear(); for (int i = 0; i < pieces.length; i++) { byte p = GamerUtils.UncastleRook(pieces[i]); if (p != GamerPieces.EMPTY) { byte pl = places[i]; if (pl <= GAME_BOARDSIZE) mGamerPieces.add(new DrawablePiece(p, GamerUtils.columnByCell(pl), GamerUtils.rowByCell(pl, true))); } } } } public void renderGamerPieces(Canvas canvas) { ... Rect r = new Rect(0, 0, mCellSize, mCellSize); List<DrawablePiece> over = new ArrayList<DrawablePiece>(); for (DrawablePiece d : mGamerPieces) { if (d.isFloating()) { over.add(d); } else { r.offsetTo(invert(d.getBoardCol()) * mCellSize, invert(d.getBoardRow()) * mCellSize); r.offset(mBoardRegion.left, mBoardRegion.top); Bitmap pic = mPieceFactory.getBitmapPiece(d.getPiece(), mCellSize); if (null != pic) canvas.drawBitmap(pic, null, r, null); } } ... } public void render(Canvas canvas) { ... synchronized (mGamerPiecesLock) { renderGamerPieces(canvas); } ... }
Thank you for comments! I will tidy up my code - add synchronization block in
renderGamerPieces
, and check canloadPosition
be called from another synchronized block.
原文:https://stackoverflow.com/questions/26544241
最满意答案
使用
git stash
。 它是为了这个目的而制作的。 如果您的仓库处于不洁净状态,但您想要结账另一个分支,或者几乎做任何git动作,那么存储就是可行的方法。 Stash创建的提交与您可以还原到任何分支的任何分支无关。 查看文档了解更多信息: https : //git-scm.com/book/no-nb/v1/Git-Tools-StashingUse
git stash
. It was made for this exact purpose. If your repo is in an unclean state, but you want to checkout another branch, or pretty much do any git action, then stash is the way to go. Stash creates a commit not related to any branch which you can restore to any branch. Check the docs for more info: https://git-scm.com/book/no-nb/v1/Git-Tools-Stashing
相关问答
更多-
重置SourceTree中的提交(Reset commit in SourceTree)[2024-03-31]
您需要在源码树终端中运行此命令git reset --soft HEAD~1此命令将您的提交推回到您的sourtree。 然后你采取最新的拉,然后你可以提交你的代码。 You need to run this command in source tree terminal git reset --soft HEAD~1 this command push back your commit in your sourtree. then you take latest pull and then you can ... -
我喜欢用 git stash 这将存储所有未提交的更改。 如果你想稍后丢弃这些更改,只需要git stash drop (或git stash pop来恢复它们)。 虽然这在技术上不是放弃变更的“适当”方式(正如其他答案和意见所指出的那样)。 I like to use git stash This stores all uncommitted changes in the stash. If you want to discard these changes later just git stash ...
-
Mercurial:我可以忽略文件的推/拉但仍然提交?(Mercurial: can I ignore a file for push/pull but still commit? (.hgsub))[2022-04-18]
推/拉不对文件进行操作,它对变更集进行操作。 因此,没有办法推/拉部分变更集,无论是你推/拉它,还是你没有。 如果您不希望存储库始终包含该文件/子存储库,则不应该像这样组织您的项目。 相反,您可能希望仅考虑其他站点所需的子存储库来设置辅助项目。 换句话说,您可能会考虑拥有2个项目,一个包含所有子回购,另一个只有几个。 A push/pull doesn't operate on files, it operates on changesets. As such, there is no way to pus ... -
首先撤销恢复提交,丢弃它创建的更改: git reset --hard HEAD^ 然后撤消更新的渲染图形提交,但将这些更改保留在工作树(本地文件)中: git reset HEAD^ First undo the revert commit, throwing away the changes it created: git reset --hard HEAD^ Then undo the updated render graphics commit, but keep those changes ...
-
使用git stash 。 它是为了这个目的而制作的。 如果您的仓库处于不洁净状态,但您想要结账另一个分支,或者几乎做任何git动作,那么存储就是可行的方法。 Stash创建的提交与您可以还原到任何分支的任何分支无关。 查看文档了解更多信息: https : //git-scm.com/book/no-nb/v1/Git-Tools-Stashing Use git stash. It was made for this exact purpose. If your repo is in an unclea ...
-
好。 以为我明白了。 在我可以根据需要进行拉/推之前,我还有2个冲突要解决。 谢谢阅读。 OK. Think I got it. I still had 2 conflicts to resolve before I can Pull / Push as desired. Thanks for reading.
-
如何使用SourceTree将指定的提交重新绑定到不同的分支?(How to rebase specified commit to different branch using SourceTree?)[2022-04-21]
最好的方式就像@ ElpieKay的评论中提到的那样,并且在问题结束时:将staging合并到warning-fixes ,然后将staging重置为先前的提交。 要从命令行执行此操作,请执行以下操作: git checkout warning-fixes git merge staging git checkout staging git reset --hard HEAD^ 在SourceTree中: 双击warning-fixes进行检查。 右键单击staging 。 单击将Merge stagin ... -
如何修复在SourceTree上意外标记为合并的提交?(How to fix a commit accidentally marked as merge on SourceTree?)[2023-03-31]
在解决冲突时,你似乎混合了一些东西。 你想将主分支合并到功能分支吗? 如果是,则应选择功能分支作为当前分支,然后单击合并 - >在主分支上选择提交。 出现合并冲突时,当前分支仍然是功能,如果在解决冲突之前切换到主分支,它将显示错误。 如果您想在解决冲突之前做出更多更改,则应取消所有 - >丢弃文件 - >切换到主分支 - >进行更多更改 - >提交。 更新主分支 - >切换功能作为当前分支 - >合并 - >选择主分支上的提交 - >解决冲突。 It seems you mix something when ... -
考虑此代码和我们的12列:54321
-
最好先提交。 拉动而不提交可能会使您的工作被覆盖。 使用本地提交时,将显示冲突并在提取时提示手动合并,从而更好地控制您的工作。 It's better to commit first. Pulling without commiting may make your work overwritten. With a local commit, conflicts will be shown and prompted for manual merging when pulling, giving you a b ...