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...");
    }
}