- private final LinkedHashMap<String, Entry> lruEntries
- = new LinkedHashMap<String, Entry>(0, 0.75f, true);
- private int redundantOpCount;
- /
- * To differentiate between old and current snapshots, each entry is given
- * a sequence number each time an edit is committed. A snapshot is stale if
- * its sequence number is not equal to its entry’s sequence number.
- */
- private long nextSequenceNumber = 0;
- / This cache uses a single background thread to evict entries. */
- private final ExecutorService executorService = new ThreadPoolExecutor(0, 1,
- 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
- private final Callable<Void> cleanupCallable = new Callable<Void>() {
- @Override public Void call() throws Exception {
- synchronized (DiskLruCache.this) {
- if (journalWriter == null) {
- return null; // closed
- }
- trimToSize();
- if (journalRebuildRequired()) {
- rebuildJournal();
- redundantOpCount = 0;
- }
- }
- return null;
- }
- };
- private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) {
- this.directory = directory;
- this.appVersion = appVersion;
- this.journalFile = new File(directory, JOURNAL_FILE);
- this.journalFileTmp = new File(directory, JOURNAL_FILE_TMP);
- this.valueCount = valueCount;
- this.maxSize = maxSize;
- }
- /
- * Opens the cache in {@code directory}, creating a cache if none exists
- * there.
- *
- * @param directory a writable directory
- * @param appVersion
- * @param valueCount the number of values per cache entry. Must be positive.
- * @param maxSize the maximum number of bytes this cache should use to store
- * @throws IOException if reading or writing the cache directory fails
- */
- public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
- throws IOException {
- if (maxSize <= 0) {
- throw new IllegalArgumentException(“maxSize <= 0”);
- }
- if (valueCount <= 0) {
- throw new IllegalArgumentException(“valueCount <= 0”);
- }
- // prefer to pick up where we left off
- DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
- if (cache.journalFile.exists()) {
- try {
- cache.readJournal();
- cache.processJournal();
- cache.journalWriter = new BufferedWriter(new FileWriter(cache.journalFile, true));
- return cache;
- } catch (IOException journalIsCorrupt) {
- System.logW("DiskLruCache " + directory + " is corrupt: "
- + journalIsCorrupt.getMessage() + “, removing”);
- cache.delete();
- }
- }
- // create a new empty cache
- directory.mkdirs();
- cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
- cache.rebuildJournal();
- return cache;
- }
- private void readJournal() throws IOException {
- InputStream in = new BufferedInputStream(new FileInputStream(journalFile));
- try {
- String magic = Streams.readAsciiLine(in);
- String version = Streams.readAsciiLine(in);
- String appVersionString = Streams.readAsciiLine(in);
- String valueCountString = Streams.readAsciiLine(in);
- String blank = Streams.readAsciiLine(in);
- if (!MAGIC.equals(magic)
- || !VERSION_1.equals(version)
- || !Integer.toString(appVersion).equals(appVersionString)
- || !Integer.toString(valueCount).equals(valueCountString)
- || !“”.equals(blank)) {
- throw new IOException(“unexpected journal header: [”
- + magic + ", " + version + ", " + valueCountString + ", " + blank + “]”);
- }
- while (true) {
- try {
- readJournalLine(Streams.readAsciiLine(in));
- } catch (EOFException endOfJournal) {
- break;
- }
- }
- } finally {
- IoUtils.closeQuietly(in);
- }
- }
- private void readJournalLine(String line) throws IOException {
- String[] parts = line.split(" ");
- if (parts.length < 2) {
- throw new IOException("unexpected journal line: " + line);
- }
- String key = parts[1];
- if (parts[0].equals(REMOVE) && parts.length == 2) {
- lruEntries.remove(key);
- return;
- }
- Entry entry = lruEntries.get(key);
- if (entry == null) {
- entry = new Entry(key);
- lruEntries.put(key, entry);
- }
- if (parts[0].equals(CLEAN) && parts.length == 2 + valueCount) {
- entry.readable = true;
- entry.currentEditor = null;
- entry.setLengths(Arrays.copyOfRange(parts, 2, parts.length));
- } else if (parts[0].equals(DIRTY) && parts.length == 2) {
- entry.currentEditor = new Editor(entry);
- } else if (parts[0].equals(READ) && parts.length == 2) {
- // this work was already done by calling lruEntries.get()
- } else {
- throw new IOException("unexpected journal line: " + line);
- }
- }
- /
- * Computes the initial size and collects garbage as a part of opening the
- * cache. Dirty entries are assumed to be inconsistent and will be deleted.
- */
- private void processJournal() throws IOException {
- deleteIfExists(journalFileTmp);
- for (Iterator<Entry> i = lruEntries.values().iterator(); i.hasNext(); ) {
- Entry entry = i.next();
- if (entry.currentEditor == null) {
- for (int t = 0; t < valueCount; t++) {
- size += entry.lengths[t];
- }
- } else {
- entry.currentEditor = null;
- for (int t = 0; t < valueCount; t++) {
- deleteIfExists(entry.getCleanFile(t));
- deleteIfExists(entry.getDirtyFile(t));
- }
- i.remove();
- }
- }
- }
- /
- * Creates a new journal that omits redundant information. This replaces the
- * current journal if it exists.
- */
- private synchronized void rebuildJournal() throws IOException {
- if (journalWriter != null) {
- journalWriter.close();
- }
- Writer writer = new BufferedWriter(new FileWriter(journalFileTmp));
- writer.write(MAGIC);
- writer.write(“\n”);
- writer.write(VERSION_1);
- writer.write(“\n”);
- writer.write(Integer.toString(appVersion));
- writer.write(“\n”);
- writer.write(Integer.toString(valueCount));
- writer.write(“\n”);
- writer.write(“\n”);
- for (Entry entry : lruEntries.values()) {
- if (entry.currentEditor != null) {
- writer.write(DIRTY + ’ ’ + entry.key + ‘\n’);
- } else {
- writer.write(CLEAN + ’ ’ + entry.key + entry.getLengths() + ‘\n’);
- }
- }
- writer.close();
- journalFileTmp.renameTo(journalFile);
- journalWriter = new BufferedWriter(new FileWriter(journalFile, true));
- }
- private static void deleteIfExists(File file) throws IOException {
- try {
- Libcore.os.remove(file.getPath());
- } catch (ErrnoException errnoException) {
- if (errnoException.errno != OsConstants.ENOENT) {
- throw errnoException.rethrowAsIOException();
- }
- }
- }
- /
- * Returns a snapshot of the entry named {@code key}, or null if it doesn’t
- * exist is not currently readable. If a value is returned, it is moved to
- * the head of the LRU queue.
- */
- public synchronized Snapshot get(String key) throws IOException {
- checkNotClosed();
- validateKey(key);
- Entry entry = lruEntries.get(key);
- if (entry == null) {
- return null;
- }
- if (!entry.readable) {
- return null;
- }
- /*
- * Open all streams eagerly to guarantee that we see a single published
- * snapshot. If we opened streams lazily then the streams could come
- * from different edits.
- */
- InputStream[] ins = new InputStream[valueCount];
- try {
- for (int i = 0; i < valueCount; i++) {
- ins[i] = new FileInputStream(entry.getCleanFile(i));
- }
- } catch (FileNotFoundException e) {
- // a file must have been deleted manually!
- return null;
- }
- redundantOpCount++;
- journalWriter.append(READ + ’ ’ + key + ‘\n’);
- if (journalRebuildRequired()) {
- executorService.submit(cleanupCallable);
- }
- return new Snapshot(key, entry.sequenceNumber, ins);
- }
- /
- * Returns an editor for the entry named {@code key}, or null if another
- * edit is in progress.
- */
- public Editor edit(String key) throws IOException {
- return edit(key, ANY_SEQUENCE_NUMBER);
- }
- private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException {
- checkNotClosed();
- validateKey(key);
- Entry entry = lruEntries.get(key);
- if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER
- && (entry == null || entry.sequenceNumber != expectedSequenceNumber)) {
- return null; // snapshot is stale
- }
- if (entry == null) {
- entry = new Entry(key);
- lruEntries.put(key, entry);
- } else if (entry.currentEditor != null) {
- return null; // another edit is in progress
- }
- Editor editor = new Editor(entry);
- entry.currentEditor = editor;
- // flush the journal before creating files to prevent file leaks
- journalWriter.write(DIRTY + ’ ’ + key + ‘\n’);
- journalWriter.flush();
- return editor;
- }
- /
- * Returns the directory where this cache stores its data.
- */
- public File getDirectory() {
- return directory;
- }
- /
- * Returns the maximum number of bytes that this cache should use to store
- * its data.
- */
- public long maxSize() {
- return maxSize;
- }
- /
- * Returns the number of bytes currently being used to store the values in
- * this cache. This may be greater than the max size if a background
- * deletion is pending.
- */
- public synchronized long size() {
- return size;
- }
- private synchronized void completeEdit(Editor editor, boolean success) throws IOException {
- Entry entry = editor.entry;
- if (entry.currentEditor != editor) {
- throw new IllegalStateException();
- }
- // if this edit is creating the entry for the first time, every index must have a value
- if (success && !entry.readable) {
- for (int i = 0; i < valueCount; i++) {
- if (!entry.getDirtyFile(i).exists()) {
- editor.abort();
- throw new IllegalStateException("edit didn’t create file " + i);
- }
- }
- }
- for (int i = 0; i < valueCount; i++) {
- File dirty = entry.getDirtyFile(i);
- if (success) {
- if (dirty.exists()) {
- File clean = entry.getCleanFile(i);
- dirty.renameTo(clean);
- long oldLength = entry.lengths[i];
- long newLength = clean.length();
- entry.lengths[i] = newLength;
- size = size - oldLength + newLength;
- }
- } else {
- deleteIfExists(dirty);
- }
- }
- redundantOpCount++;
- entry.currentEditor = null;
- if (entry.readable | success) {
- entry.readable = true;
- journalWriter.write(CLEAN + ’ ’ + entry.key + entry.getLengths() + ‘\n’);
- if (success) {
- entry.sequenceNumber = nextSequenceNumber++;
- }
- } else {
- lruEntries.remove(entry.key);
- journalWriter.write(REMOVE + ’ ’ + entry.key + ‘\n’);
- }
- if (size > maxSize || journalRebuildRequired()) {
- executorService.submit(cleanupCallable);
- }
- }
- /
- * We only rebuild the journal when it will halve the size of the journal
- * and eliminate at least 2000 ops.
- */
- private boolean journalRebuildRequired() {
- final int REDUNDANT_OP_COMPACT_THRESHOLD = 2000;
- return redundantOpCount >= REDUNDANT_OP_COMPACT_THRESHOLD
- && redundantOpCount >= lruEntries.size();
- }
- /
- * Drops the entry for {@code key} if it exists and can be removed. Entries
- * actively being edited cannot be removed.
- *
- * @return true if an entry was removed.
- */
- public synchronized boolean remove(String key) throws IOException {
- checkNotClosed();
- validateKey(key);
- Entry entry = lruEntries.get(key);
- if (entry == null || entry.currentEditor != null) {
- return false;
- }
- for (int i = 0; i < valueCount; i++) {
- File file = entry.getCleanFile(i);
- if (!file.delete()) {
- throw new IOException("failed to delete " + file);
- }
- size -= entry.lengths[i];
- entry.lengths[i] = 0;
- }
- redundantOpCount++;
- journalWriter.append(REMOVE + ’ ’ + key + ‘\n’);
- lruEntries.remove(key);
- if (journalRebuildRequired()) {
- executorService.submit(cleanupCallable);
- }
- return true;
- }
- /
- * Returns true if this cache has been closed.
- */
- public boolean isClosed() {
- return journalWriter == null;
- }
- private void checkNotClosed() {
- if (journalWriter == null) {
- throw new IllegalStateException(“cache is closed”);
- }
- }
- /
- * Force buffered operations to the filesystem.
- */
- public synchronized void flush() throws IOException {
- checkNotClosed();
- trimToSize();
- journalWriter.flush();
- }
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。




由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)

这里我就分享一份资料,希望可以帮助到大家提升进阶。
内容包含:Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容。分享给大家,非常适合近期有面试和想在技术道路上继续精进的朋友。
如果你有需要的话,可以点击Android学习PDF+架构视频+面试文档+源码笔记获取免费领取方式
喜欢本文的话,不妨给我点个小赞、评论区留言或者转发支持一下呗~
- }
- /
- * Returns true if this cache has been closed.
- */
- public boolean isClosed() {
- return journalWriter == null;
- }
- private void checkNotClosed() {
- if (journalWriter == null) {
- throw new IllegalStateException(“cache is closed”);
- }
- }
- /
- * Force buffered operations to the filesystem.
- */
- public synchronized void flush() throws IOException {
- checkNotClosed();
- trimToSize();
- journalWriter.flush();
- }
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-OWI0FRCb-63)]
[外链图片转存中…(img-P9DV0VpD-63)]
[外链图片转存中…(img-dzmqOyw4-63)]
[外链图片转存中…(img-mC24F0Z9-64)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-cWofcRqd-64)]
这里我就分享一份资料,希望可以帮助到大家提升进阶。
内容包含:Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容。分享给大家,非常适合近期有面试和想在技术道路上继续精进的朋友。
如果你有需要的话,可以点击Android学习PDF+架构视频+面试文档+源码笔记获取免费领取方式
喜欢本文的话,不妨给我点个小赞、评论区留言或者转发支持一下呗~


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/13174.html