Android4,Spring都没弄明白凭什么拿高薪

}

}

//读取日志中某行日志信息

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(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.

* 处理日志

* 计算初始化cache的初始化大小和收集垃圾。Dirty entry假定不一致将会被删掉。

*/

private void processJournal() throws IOException {

deleteIfExists(journalFileTmp);//删除日志文件

for (Iterator 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), IO_BUFFER_SIZE);

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), IO_BUFFER_SIZE);

}

//文件若存在删除

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();

//            }

//        }

if (file.exists() && !file.delete()) {

throw new IOException();

}

}

/**

* 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.

* 返回key对应的entry的snapshot,当key相应的entry不存在或者当前不可读时返回null。

* 如果返回相应的值,它就会被移动到LRU队列的头部。

*/

public synchronized Snapshot get(String key) throws IOException {

checkNotClosed();//检查cache是否已关闭

validateKey(key);//验证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);

}

//有key和序列号生成一个editor

private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException {

checkNotClosed();//检查cache关闭与否

validateKey(key);//验证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;

}

//完成Edit动作

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.

* 当日志大小减半并且删掉至少2000项时重新构造日志

*/

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.

* 删除key相应的entry,被编辑的Entry不能被remove

* @return true if an entry was removed.

*/

public synchronized boolean remove(String key) throws IOException {

checkNotClosed();//检查cache是否已经关闭

validateKey(key);//验证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.

* 判断cache是否已经关闭

*/

public boolean isClosed() {

return journalWriter == null;

}

//检查cache是否已经关闭

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();//检查cache是否关闭

trimToSize();//满足最大空间limit

journalWriter.flush();

}

/**

* Closes this cache. Stored values will remain on the filesystem.

* 关闭cache。

*/

public synchronized void close() throws IOException {

if (journalWriter == null) {

return; // already closed

}

for (Entry entry : new ArrayList(lruEntries.values())) {

if (entry.currentEditor != null) {

entry.currentEditor.abort();

}

}

trimToSize();

journalWriter.close();

journalWriter = null;

}

//回收删除某些entry到空间大小满足maxsize

private void trimToSize() throws IOException {

while (size > maxSize) {

//            Map.Entry<String, Entry> toEvict = lruEntries.eldest();

final Map.Entry<String, Entry> toEvict = lruEntries.entrySet().iterator().next();

remove(toEvict.getKey());

}

}

/**

* Closes the cache and deletes all of its stored values. This will delete

* all files in the cache directory including files that weren’t created by

* the cache.

* 关闭删除cache

*/

public void delete() throws IOException {

close();

deleteContents(directory);

}

//验证key格式的正确性

private void validateKey(String key) {

if (key.contains(" “) || key.contains(”\n") || key.contains("\r")) {

throw new IllegalArgumentException(

“keys must not contain spaces or newlines: \”" + key + “\”");

}

}

//字符串形式读出输入流的内容

private static String inputStreamToString(InputStream in) throws IOException {

return readFully(new InputStreamReader(in, UTF_8));

}

/**

* A snapshot of the values for an entry.

* entry的快照

*/

public final class Snapshot implements Closeable {

private final String key;//key

private final long sequenceNumber;//序列号(同文件名称)

private final InputStream[] ins;//两个修改的文件输入流

private Snapshot(String key, long sequenceNumber, InputStream[] ins) {

this.key = key;

this.sequenceNumber = sequenceNumber;

this.ins = ins;

}

/**

* Returns an editor for this snapshot’s entry, or null if either the

* entry has changed since this snapshot was created or if another edit

* is in progress.

* 返回entry快照的editor,如果entry已经更新了或者另一个edit正在处理过程中返回null。

*/

public Editor edit() throws IOException {

return DiskLruCache.this.edit(key, sequenceNumber);

}

/**

* Returns the unbuffered stream with the value for {@code index}.

*/

public InputStream getInputStream(int index) {

return ins[index];

}

/**

* Returns the string value for {@code index}.

*/

public String getString(int index) throws IOException {

return inputStreamToString(getInputStream(index));

}

@Override public void close() {

for (InputStream in : ins) {

closeQuietly(in);

}

}

}

/**

* Edits the values for an entry.

* entry编辑器

*/

public final class Editor {

private final Entry entry;

private boolean hasErrors;

private Editor(Entry entry) {

this.entry = entry;

}

/**

* Returns an unbuffered input stream to read the last committed value,

* or null if no value has been committed.

* 返回一个最后提交的entry的不缓存输入流,如果没有值被提交过返回null

*/

public InputStream newInputStream(int index) throws IOException {

synchronized (DiskLruCache.this) {

if (entry.currentEditor != this) {

throw new IllegalStateException();

}

if (!entry.readable) {

return null;

}

return new FileInputStream(entry.getCleanFile(index));

}

}

/**

* Returns the last committed value as a string, or null if no value

* has been committed.

* 返回最后提交的entry的文件内容,字符串形式

*/

public String getString(int index) throws IOException {

InputStream in = newInputStream(index);

return in != null ? inputStreamToString(in) : null;

}

/**

* Returns a new unbuffered output stream to write the value at

* {@code index}. If the underlying output stream encounters errors

* when writing to the filesystem, this edit will be aborted when

* {@link #commit} is called. The returned output stream does not throw

* IOExceptions.

* 返回一个新的无缓冲的输出流,写文件时如果潜在的输出流存在错误,这个edit将被废弃。

*/

public OutputStream newOutputStream(int index) throws IOException {

synchronized (DiskLruCache.this) {

if (entry.currentEditor != this) {

throw new IllegalStateException();

}

return new FaultHidingOutputStream(new FileOutputStream(entry.getDirtyFile(index)));

}

}

/**

* Sets the value at {@code index} to {@code value}.

* 设置entry的value的文件的内容

*/

public void set(int index, String value) throws IOException {

Writer writer = null;

try {

writer = new OutputStreamWriter(newOutputStream(index), UTF_8);

writer.write(value);

} finally {

closeQuietly(writer);

}

}

/**

* Commits this edit so it is visible to readers.  This releases the

* edit lock so another edit may be started on the same key.

* commit提交编辑的结果,释放edit锁然后其它edit可以启动

*/

public void commit() throws IOException {

if (hasErrors) {

completeEdit(this, false);

remove(entry.key); // the previous entry is stale

} else {

completeEdit(this, true);

}

}

/**

* Aborts this edit. This releases the edit lock so another edit may be

* started on the same key.

* 废弃edit,释放edit锁然后其它edit可以启动

*/

public void abort() throws IOException {

completeEdit(this, false);

}

//包装的输出流类

private class FaultHidingOutputStream extends FilterOutputStream {

private FaultHidingOutputStream(OutputStream out) {

super(out);

}

@Override public void write(int oneByte) {

try {

out.write(oneByte);

} catch (IOException e) {

hasErrors = true;

}

}

@Override public void write(byte[] buffer, int offset, int length) {

try {

out.write(buffer, offset, length);

} catch (IOException e) {

hasErrors = true;

}

}

@Override public void close() {

try {

out.close();

} catch (IOException e) {

hasErrors = true;

}

}

@Override public void flush() {

try {

out.flush();

} catch (IOException e) {

hasErrors = true;

}

}

}

}

/*

* Entry 最终类

*/

private final class Entry {

private final String key;

/** Lengths of this entry’s files. */

private final long[] lengths;//每一个cache文件的长度

/** True if this entry has ever been published */

private boolean readable;

/** The ongoing edit or null if this entry is not being edited. */

private Editor currentEditor;

/** The sequence number of the most recently committed edit to this entry. */

private long sequenceNumber;

private Entry(String key) {

this.key = key;

this.lengths = new long[valueCount];

}

public String getLengths() throws IOException {

StringBuilder result = new StringBuilder();

for (long size : lengths) {

result.append(’ ').append(size);

}

return result.toString();

}

/**

* Set lengths using decimal numbers like “10123”.

* 设置每一个cache文件的长度(即lengths[i]的长度)

*/

private void setLengths(String[] strings) throws IOException {

if (strings.length != valueCount) {

throw invalidLengths(strings);

尾声

一转眼时间真的过的飞快。我们各奔东西,也各自踏上了自己的旅途,但是即使多年不见,也因为这份情谊我们依旧如从前那般“亲密”。不忘初心方得始终。加油吧,程序员们,在我看来35岁,40岁从来不是危机,只要永远不要忘记自己为何踏上征程!

最后需要同款资料的,可以 **私信我点击【学习】**我愿意分享给你!

为了让更多在学习中或者最近要准备面试的朋友们看到这篇文章,希望你们能多多评论,点赞+转发!

再次感谢所有给我提供过题目的朋友们,感谢一路有你!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值