进程间锁, 仅在同一个应用中有效.
| 22 | * 进程间锁, 仅在同一个应用中有效. |
| 23 | */ |
| 24 | public final class ProcessLock implements Closeable { |
| 25 | |
| 26 | private final String mLockName; |
| 27 | private final FileLock mFileLock; |
| 28 | private final File mFile; |
| 29 | private final Closeable mStream; |
| 30 | private final boolean mWriteMode; |
| 31 | |
| 32 | private final static String LOCK_FILE_DIR = "process_lock"; |
| 33 | /** |
| 34 | * key1: lockName |
| 35 | * key2: fileLock.hashCode() |
| 36 | */ |
| 37 | private final static DoubleKeyValueMap<String, Integer, ProcessLock> LOCK_MAP = new DoubleKeyValueMap<String, Integer, ProcessLock>(); |
| 38 | |
| 39 | static { |
| 40 | File dir = x.app().getDir(LOCK_FILE_DIR, Context.MODE_PRIVATE); |
| 41 | IOUtil.deleteFileOrDir(dir); |
| 42 | } |
| 43 | |
| 44 | private ProcessLock(String lockName, File file, FileLock fileLock, Closeable stream, boolean writeMode) { |
| 45 | mLockName = lockName; |
| 46 | mFileLock = fileLock; |
| 47 | mFile = file; |
| 48 | mStream = stream; |
| 49 | mWriteMode = writeMode; |
| 50 | } |
| 51 | |
| 52 | /** |
| 53 | * 获取进程锁 |
| 54 | * |
| 55 | * @param lockName 锁的名称, 相同的名称被认为是同一个锁. |
| 56 | * @param writeMode 是否写入模式(支持读并发). |
| 57 | * @return null 或 进程锁, 如果锁已经被占用, 返回null. |
| 58 | */ |
| 59 | public static ProcessLock tryLock(final String lockName, final boolean writeMode) { |
| 60 | return tryLockInternal(lockName, customHash(lockName), writeMode); |
| 61 | } |
| 62 | |
| 63 | /** |
| 64 | * 获取进程锁 |
| 65 | * |
| 66 | * @param lockName 锁的名称, 相同的名称被认为是同一个锁. |
| 67 | * @param writeMode 是否写入模式(支持读并发). |
| 68 | * @param maxWaitTimeMillis 最大值 1000 * 60 |
| 69 | * @return null 或 进程锁, 如果锁已经被占用, 则在超时时间内继续尝试获取该锁. |
| 70 | */ |
| 71 | public static ProcessLock tryLock(final String lockName, final boolean writeMode, final long maxWaitTimeMillis) throws InterruptedException { |
| 72 | ProcessLock lock = null; |
| 73 | long expiryTime = System.currentTimeMillis() + maxWaitTimeMillis; |
| 74 | String hash = customHash(lockName); |
| 75 | synchronized (LOCK_MAP) { |
| 76 | while (System.currentTimeMillis() < expiryTime) { |
| 77 | lock = tryLockInternal(lockName, hash, writeMode); |
| 78 | if (lock != null) { |
| 79 | break; |
| 80 | } else { |
| 81 | try { |
nothing calls this directly
no test coverage detected