我正在構建一個處理物件繪制的 WebSocket 服務器。以下是該服務器類的外觀:
import fmi.whiteboard.models.paths.*;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections。
import java.util.HashSet;
import java.util.Set;
public class WhiteboardServer {
private static Set<Session> peers = Collections.synchronizedSet(new HashSet< Session> ())。
public void onOpen(Session peer) {
peers.add(peer)。
}
public void onClose(會話peer) {
peers.remove(peer)。
}
public void broadcastShape(Drawing drawing, Session session) throws IOException, EncodeException {
for (Session peer : peers) {
if (!peer.equals(session)) {
peer.getAsyncRemote().sendObject(繪圖)。
}
}
}
}
而這里是處理繪圖的ReactJS組件的樣子:
export default function Whiteboard() {
const canvas = useRef(null)。
const ws = useMemo(()=> {
const socket = new WebSocket("ws: //localhost:8080/backend_war/whiteboard")。)
socket.binaryType = "arraybuffer"。
return socket。
}, []);
useEffect(() => {
ws.onmessage = (evt: MessageEvent) => {
const data: SocketResponse = JSON.parse(evt.data)。
if (data && data.shapes) {
canvas?.current?.loadPaths(data.shapes)。
}
};
ws.onerror= (err) => console.log(err)。
}, [ws])。
const onDraw = (message: CanvasPath[] ) => {
ws.send(JSON.stringify({ shapes: message }))。
};
return (
<>
<ReactSketchCanvas
ref={canvas}
style={styles}
onUpdate={(paths) => setPaths(paths)}
strokeWidth={4}。
strokeColor={"red"}。
/>
</>
);
}
該應用程式在2-3秒內作業正常,但是當我開始繪制更多的圖形時,套接字服務器在for (Session peer : peers)這一行崩潰了,出現了ConcurrentModificationException。
如果有什么幫助的話,我使用 Java 11 和 Tomcat 10 作為服務器。
uj5u.com熱心網友回復:
Collections.synchronizedSet創建了一個單項訪問被同步的Set。這涉及到諸如get、add、remove等方法。 然而,迭代器并不是同步的。當另一個執行緒在迭代程序中修改了集合時,你會得到 ConcurrentModificationException。
您有兩種解決方案。一種是用一個同步塊來保護外觀,如:
你有兩個解決方案。
synchronized(peers) {
for (Session peer: peers) {
...
}
}
或者,更好的是,切換到ConcurrentHashSet,它保證了多執行緒的優化訪問,而絕不會拋出ConcurrentModificationException。
uj5u.com熱心網友回復:
當你用Collections.synchronizedSet來同步現有的集合時,它只同步了訪問資料的方法,如get(), set()...而不是迭代器。因此,你需要把迭代器也同步化,比如說
synchronized(peers){
for (Session peer : peers) {
if (!peer.equals(session)) {
peer.getAsyncRemote().sendObject(繪圖)。
}
}
}
這里是檔案
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/319424.html
標籤:
