我有一個正在被主線程實例化的類。然後這個類產生第二個線程,即處理線程。處理線程調用該類的某些方法(處理方法),訪問/更改字段。這些方法和字段永遠不會被處理線程以外的其他任何東西訪問。但是,初始化它們的構造函數在主線程上運行。在Thread 2中調用的構造函數,在Thread 2中專門訪問的字段 - volatile需要嗎?
該類擴展了一個通用「協議」類,該類包含輸入處理線程,該線程調用處理收到的消息的函數。本來,我是自動啓動的泛型類的構造函數,它原來是一個非常愚蠢的想法處理線程:
- 子類稱爲超級構造
- 超級構造函數啓動線程
- 線程立即使用空消息調用消息處理方法(以使其在協議中發送第一條消息)。該方法設置了「發送消息計數器」。
- 在主線程上,超級構造函數返回,並且子類初始化設置消息計數器,將其重置爲零。
我現在已經被加工螺紋的起點移動到另一個方法,並在子類的構造函數的最後調用它改變了它:
public ProtocolSubclass() {
super();
startProcessingThread();
}
我認爲當我打電話startProcessingThreads( ),該字段保證被初始化。在調用startProcessingThread()後,只能從該線程訪問該字段。 我可以這樣做嗎?我是否需要將字段標記爲易失性的,因爲它在主線程上初始化,但在處理線程上讀取?
我想我猜中了這個時間,但調試上述問題小時後,我寧願問...
按照要求,這裏是略爲詳細(還是簡化的)代碼。請注意,上面的代碼更加簡化,因此可能不完全符合以下代碼。這是演戲了本場是currentMsg:
public abstract class ProtocolConnection {
public ProtocolConnection(/*stuff*/) {
/*stuff*/
// DO NOT DO THIS HERE: startProcessingThreads();
}
protected void startProcessingThreads() {
inputProcessingThread.start();
}
private final Thread inputProcessingThread = new Thread() {
public void run() {
if (isInitiator) initiateConnection();
while (!closed && !finished) {
ProtocolMessage msg = new ProtocolMessage(inputStream);
log("received", Integer.toString(msg.tag), Integer.toString(msg.length));
ProtocolConnection.this.processMessage(msg);
}
}
};
}
public class SimpleProtocolConnection extends ProtocolConnection {
private int currentMsg = 0;
public SimpleProtocolConnection(/*stuff*/) {
super(/*stuff*/);
startProcessingThreads();
}
@Override
protected void processMessage(ProtocolMessage msg) {
if (msg.tag != LAST_MESSAGE) {
sendNext();
}
}
@Override
protected void initiateConnection() {
sendNext();
}
private void sendNext() {
addToSendingQueue(new ProtocolMessage(currentMsg, getData())); // very simplified
currentMsg++;
}
}
你能提供更多的代碼來真正體現安裝嗎? – 2013-03-13 02:25:40
如果在構造函數中設置的所有字段都是'final'(這是不太可能的),那麼你不必擔心。 – user949300 2013-03-13 02:40:47
@MattBall:添加代碼。 – 2013-03-13 02:53:44