我已經寫了一些多線程的愛好程序和一些在我以前的(工程/物理)研究中,所以我認爲我有一個在同步/線程安全和原語,普通用戶發現與JMM和多線程等進行交談。Java:線程共享數據的框架
我發現我需要並且沒有適當的方法來標記不同線程共享的實例或靜態成員類。考慮一下,我們有訪問規則,如私人/保護/公共和關於如何命名getters/setters和許多事情的約定。
但是線程呢?如果我想將變量標記爲線程共享並且遵循特定規則,該怎麼辦? Volatile/Atomic refs可能會完成這項工作,但有時您只需要使用互斥鎖。當你手動記住使用某些東西時......你會忘記它:) - 在某個時刻。
所以我有一個想法,我看到我不是第一個,我也檢查出http://checkthread.org/example-threadsafe.html - 他們似乎有一個相當不錯的代碼分析器,我可能會稍後嘗試哪種讓我做一些事情我想。
但是回到最初的問題。假設我們需要比消息傳遞框架更低級別的東西,並且我們需要比原始互斥體更高級別的東西...我們有什麼...唔...什麼都沒有?
所以基本上,我所做的是一種純Java超線程框架,可以讓您將類成員聲明爲共享或非共享...以及:)。
下面是它如何被使用的例子:
public class SimClient extends AbstractLooper {
private static final int DEFAULT_HEARTBEAT_TIMEOUT_MILLIS = 2000;
// Accessed by single threads only
private final SocketAddress socketAddress;
private final Parser parser;
private final Callback cb;
private final Heart heart;
private boolean lookingForFirstMsg = true;
private BufferedInputStream is;
// May be accessed by several threads (T*)
private final Shared<AllThreadsVars> shared = new Shared<>(new AllThreadsVars());
.
.
.
.
static class AllThreadsVars {
public boolean connected = false;
public Socket socket = new Socket();
public BufferedOutputStream os = null;
public long lastMessageAt = 0;
}
並訪問標記爲線程共享你必須發送一個可運行的樣函子來共享對象的變量:
public final void transmit(final byte[] data) {
shared.run(new SharedRunnable<AllThreadsVars, Object, Object>() {
@Override
public Object run(final AllThreadsVars sharedVariable, final Object input) {
try {
if (sharedVariable.socket.isConnected() && sharedVariable.os != null) {
sharedVariable.os.write(data);
sharedVariable.os.flush();
}
} catch (final Exception e) { // Disconnected
setLastMessageAt(0);
}
return null;
}
}, null);
}
其中共享運行如下定義:
public interface SharedRunnable<SHARED_TYPE, INPUT, OUTPUT> {
OUTPUT run(final SHARED_TYPE s, final INPUT input);
}
這是怎麼回事? 好吧,這給了我幫助(是的,你可以泄漏並打破它,但不太可能),我可以將變量集(不僅僅是變量)標記爲線程共享,並且一旦完成,在編譯時保證它不能忘記來同步一些方法)。它還允許我標準化和執行測試,以在編譯時尋找可能的死鎖(儘管atm我只在運行時實現,因爲在編譯時使用上述框架來完成它可能不僅僅需要java編譯器)。
基本上這對我來說是非常有用的,我想知道如果我只是在這裏重新發明輪子,或者這可能是一些我不知道的反模式。我真的不知道該問誰。 (噢和共享 .RUN(SharedRunnable R,INPUT輸入)的作品就像
private final <OUTPUT, INPUT> OUTPUT run(final SharedRunnable<SHARED_TYPE, INPUT, OUTPUT> r, final INPUT input) {
try {
lock.lock();
return r.run(sharedVariable, input);
} finally {
lock.unlock();
}
}
這只是我自己的實驗,所以它不是一個真正以任何方式完成,但我有一個體面項目現在使用它,它真的幫助了很多。
這裏有問題嗎? – Daniel
我不認爲我理解你的例子,但**共享變量**正是你在處理併發時不想擁有的**。帶鎖的共享變量將使您移動速度變慢,浪費更多時間來等待鎖,一般情況下響應速度較慢並陷入死鎖。達到真正併發的最好方法是根本沒有共享狀態。 –
是的,但是在您的應用程序的某個時刻,如果它需要多個線程,它將需要一些共享變量,無論是消息隊列還是其他東西。我的想法是有辦法構建任意類似原子的操作(並且重要的是:在共享標記的狀態下在編譯時強制使用它們)。此外,我可以毫不費力地爲此寫一個死鎖分析工具,因爲我所有的線程都使用標準化的框架。我已經寫了一個相當簡單的變體,並且可以在我的代碼中檢測到一些潛在的死鎖位置。 – gigurra