Long Polling vs WebSocket em Java: o que escolher para tempo real?

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Long Polling vs WebSocket em Java: duelo de tecnologias de tempo real

\n\n

Imagine: você está desenvolvendo um chat, um terminal de ações ou um jogo online em Java. O usuário espera por atualizações, mas o servidor fica em silêncio. Como fazer os dados chegarem instantaneamente? Antes havia apenas uma saída — Long Polling. Hoje, a arena é do WebSocket. Mas quem vence na luta real?

\n\n

Neste artigo, não vamos apenas comparar conceitos. Vamos escrever código vivo em Java, observar os detalhes internos de ambas as tecnologias e decidir o que usar no seu próximo projeto. Bem-vindo ao ringue!

\n\n

O que é Long Polling (e por que não é "polling")?

\n\n

O HTTP clássico é como uma carta: enviou requisição → recebeu resposta. Se o servidor não tem nada a dizer, ele retorna uma resposta vazia. O cliente é forçado a perguntar novamente a cada N segundos. Isso é Short Polling — um caminho sem saída.

\n\n

Long Polling funciona de forma mais inteligente. O cliente envia uma requisição, e o servidor… adormece. Ele mantém a conexão aberta até que um novo evento ocorra (ou até o tempo limite expirar). Assim que o evento acontece — o servidor acorda e envia a resposta. O cliente imediatamente cria uma nova requisição Long Polling. O ciclo se fecha.

\n\n

Long Polling em Java: implementação simples

\n\n

Vamos imaginar que estamos escrevendo um servidor de notificações usando apenas Servlet API (sem Spring, para ficar mais claro). Para Long Polling, precisaremos de processamento assíncrono (AsyncContext), caso contrário o servidor bloqueará todas as threads.

\n\n
import javax.servlet.AsyncContext;\nimport javax.servlet.annotation.WebServlet;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\n\n@WebServlet(urlPatterns = "/long-poll", asyncSupported = true)\npublic class LongPollingServlet extends HttpServlet {\n\n    // Fila para armazenar conexões "adormecidas"\n    private static final Queue<AsyncContext> WAITING_CLIENTS = new ConcurrentLinkedQueue<>();\n\n    @Override\n    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {\n        AsyncContext asyncContext = req.startAsync();\n        asyncContext.setTimeout(30_000); // Timeout de 30 segundos\n\n        // Salva o contexto\n        WAITING_CLIENTS.add(asyncContext);\n\n        // Se o timeout expirar — retorna resposta vazia\n        asyncContext.addListener(new javax.servlet.AsyncListener() {\n            public void onTimeout(javax.servlet.AsyncEvent event) {\n                WAITING_CLIENTS.remove(asyncContext);\n                try {\n                    HttpServletResponse response = (HttpServletResponse) event.getAsyncContext().getResponse();\n                    response.getWriter().write("timeout");\n                    response.setStatus(HttpServletResponse.SC_OK);\n                    asyncContext.complete();\n                } catch (IOException e) { e.printStackTrace(); }\n            }\n            // Outros métodos do listener omitidos por brevidade\n        });\n    }\n\n    // Este método é chamado quando um novo evento ocorre\n    public static void sendEventToClients(String message) {\n        for (AsyncContext ctx : WAITING_CLIENTS) {\n            try {\n                HttpServletResponse response = (HttpServletResponse) ctx.getResponse();\n                response.getWriter().write(message);\n                response.setStatus(HttpServletResponse.SC_OK);\n                ctx.complete();\n                WAITING_CLIENTS.remove(ctx);\n            } catch (IOException e) { e.printStackTrace(); }\n        }\n    }\n}
\n\n

Como funciona:

\n
    \n
  • O cliente faz uma requisição GET para /long-poll.
  • \n
  • O servidor coloca a requisição em modo assíncrono e "adormece" (espera).
  • \n
  • Quando uma mensagem aparece (método sendEventToClien
  • \n

Blogs

Book Recommendations