Java8:Sonar兼容的服务器套接字
下面是我的服务器套接字线程的Java8:Sonar兼容的服务器套接字,java,sockets,sonarqube-scan,Java,Sockets,Sonarqube Scan,下面是我的服务器套接字线程的run(),它将作为Executors.newWorkStealingPool().submit(()->mainServer.run())运行并接受客户端连接。它运行正常,但声纳抱怨说Bug类型的循环不应该是无限的(squid:S2189) 有人能帮我优化上述代码块以消除声纳投诉吗?将您的运行标记为volatile volatile将对可见的变量标记为可被其他线程更改1。这意味着优化程序(或代码分析器,如SonarQube)不能假设其他线程不修改此类变量。在您的示例
run()
,它将作为Executors.newWorkStealingPool().submit(()->mainServer.run())运行代码>并接受客户端连接。它运行正常,但声纳
抱怨说Bug
类型的循环不应该是无限的(squid:S2189)
有人能帮我优化上述代码块以消除声纳投诉吗?将您的
运行标记为volatile
volatile
将对可见的变量标记为可被其他线程更改1。这意味着优化程序(或代码分析器,如SonarQube)不能假设其他线程不修改此类变量。在您的示例中,这两种方法都可以假定运行的永远不会更改,从而将代码标记为具有无限循环。可以找到一个类似的例子
如果其他线程可以访问和修改变量,则应将变量标记为volatile
1由用户207421纠正那么,为什么不应用警告所说的内容,并在(运行){…}
循环时使不无限?您从未更改共享代码中的running
变量。@Fureeish用完整的代码更新了问题,mainServer
将作为Executors运行。newWorkStealingPool().submit(()->mainServer.run())当应用程序停止时,调用shutdown()
它将被停止将running
标记为volatile
摆脱bug?@Fureeish是的,令人惊讶地将running
标记为volatile
摆脱bug,它背后的魔力是什么?请看我的答案,我试图简要地解释发生了什么,并提供一些额外的读取。其他线程已经可以看到volatile
表示它可以被其他线程更改。
class MainServer {
private final ServerSocket serverSocket;
private final boolean checkClientCerts;
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(MainServer.class.getName());
private final int threadPoolSize;
private boolean running;
private ExecutorService executorService;
MainServer(int port, boolean checkClientCerts, int threadPoolSize, InetAddress bindAddress) throws IOException {
LOG.debug("Locating server socket factory for SSL...");
SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
LOG.debug("Creating a server socket on port " + port);
SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(port, 0, bindAddress);
this.checkClientCerts = checkClientCerts;
this.threadPoolSize = threadPoolSize;
}
void run() {
running = true;
DefaultThreadFactory threadFactory = new DefaultThreadFactory("SSLHandshake");
executorService = new ShutdownThreadPoolExecutor(threadPoolSize,threadFactory);
while (running) {
Socket clientSocket;
try {
clientSocket = serverSocket.accept();
MainServerHandshakeThread handshakeThread = new MainServerHandshakeThread(clientSocket, this);
executorService.submit(handshakeThread);
} catch (IOException ex) {
LOG.error("Error accepting connection",ex);
}
}
}
public void shutdown() {
LOG.info("Stopping main server...");
running = false;
try {
if (serverSocket!=null) {
serverSocket.close();
}
} catch(IOException ex) {
LOG.debug("Failed to close socket",ex);
}
executorService.shutdown();
try {
if (!executorService.awaitTermination(500, TimeUnit.MILLISECONDS)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
LOG.info("Main server stopped...");
}
}