From 71683c495073a1b8aa2493bf337467d8edd171fd Mon Sep 17 00:00:00 2001 From: ZhouXY108 Date: Sat, 9 Sep 2023 11:13:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20ReadWriteLock=20=E5=8C=85?= =?UTF-8?q?=E8=A3=85=E7=9A=84=20Table?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commons/collection/LockedTable.java | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 src/main/java/xyz/zhouxy/plusone/commons/collection/LockedTable.java diff --git a/src/main/java/xyz/zhouxy/plusone/commons/collection/LockedTable.java b/src/main/java/xyz/zhouxy/plusone/commons/collection/LockedTable.java new file mode 100644 index 0000000..bc5a4b1 --- /dev/null +++ b/src/main/java/xyz/zhouxy/plusone/commons/collection/LockedTable.java @@ -0,0 +1,276 @@ +package xyz.zhouxy.plusone.commons.collection; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Table; +import xyz.zhouxy.plusone.commons.annotation.ReaderMethod; +import xyz.zhouxy.plusone.commons.annotation.WriterMethod; + +import javax.annotation.concurrent.ThreadSafe; +import java.util.Collection; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * 使用 {@link ReentrantReadWriteLock} 将 {@link Table} 包装为线程安全的集合。 + * + *

+ * 可通过以下方式构建一个线程安全的 {@link Table} + *

+ * + *
+ * LockedTable.of(HashBasedTable.create())
+ * 
+ * + *

+ * NOTE: 如果 {@link Table} 不需要更改,请使用 {@link ImmutableTable} + *

+ * + * @author ZhouXY + * @see Table + * @see ImmutableTable + * @since 0.1.0-SNAPSHOT + */ +@Beta +@ThreadSafe +public class LockedTable implements Table { + + private final Table table; + + private final ReentrantReadWriteLock.ReadLock readLock; + private final ReentrantReadWriteLock.WriteLock writeLock; + + private LockedTable(Table table, boolean fair) { + this.table = Objects.requireNonNull(table); + ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(fair); + this.readLock = rwl.readLock(); + this.writeLock = rwl.writeLock(); + } + + public static LockedTable of(Table table) { + if (table instanceof LockedTable) { + return (LockedTable) table; + } else { + return new LockedTable<>(table, false); + } + } + + public static LockedTable of(Table table, boolean fair) { + if (table instanceof LockedTable) { + return (LockedTable) table; + } else { + return new LockedTable<>(table, fair); + } + } + + @Override + @ReaderMethod + public boolean contains(Object rowKey, Object columnKey) { + readLock.lock(); + try { + return this.table.contains(rowKey, columnKey); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public boolean containsRow(Object rowKey) { + readLock.lock(); + try { + return this.table.containsRow(rowKey); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public boolean containsColumn(Object columnKey) { + readLock.lock(); + try { + return this.table.containsColumn(columnKey); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public boolean containsValue(Object value) { + readLock.lock(); + try { + return this.table.containsValue(value); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public V get(Object rowKey, Object columnKey) { + readLock.lock(); + try { + return this.table.get(rowKey, columnKey); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public boolean isEmpty() { + readLock.lock(); + try { + return this.table.isEmpty(); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public int size() { + readLock.lock(); + try { + return this.table.size(); + } finally { + readLock.unlock(); + } + } + + @Override + @WriterMethod + public void clear() { + writeLock.lock(); + try { + this.table.clear(); + } finally { + writeLock.unlock(); + } + } + + @Override + @WriterMethod + public V put(R rowKey, C columnKey, V value) { + writeLock.lock(); + try { + return this.table.put(rowKey, columnKey, value); + } finally { + writeLock.unlock(); + } + } + + @Override + @WriterMethod + public void putAll(Table table) { + writeLock.lock(); + try { + this.table.putAll(table); + } finally { + writeLock.unlock(); + } + } + + @Override + @WriterMethod + public V remove(Object rowKey, Object columnKey) { + writeLock.lock(); + try { + return this.table.remove(rowKey, columnKey); + } finally { + writeLock.unlock(); + } + } + + @Override + @ReaderMethod + public Map row(R rowKey) { + readLock.lock(); + try { + return this.table.row(rowKey); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public Map column(C columnKey) { + readLock.lock(); + try { + return this.table.column(columnKey); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public Set> cellSet() { + readLock.lock(); + try { + return this.table.cellSet(); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public Set rowKeySet() { + readLock.lock(); + try { + return this.table.rowKeySet(); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public Set columnKeySet() { + readLock.lock(); + try { + return this.table.columnKeySet(); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public Collection values() { + readLock.lock(); + try { + return this.table.values(); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public Map> rowMap() { + readLock.lock(); + try { + return this.table.rowMap(); + } finally { + readLock.unlock(); + } + } + + @Override + @ReaderMethod + public Map> columnMap() { + readLock.lock(); + try { + return this.table.columnMap(); + } finally { + readLock.unlock(); + } + } +}