2626package org .java_websocket ;
2727
2828import org .java_websocket .framing .CloseFrame ;
29+ import org .java_websocket .util .NamedThreadFactory ;
2930import org .slf4j .Logger ;
3031import org .slf4j .LoggerFactory ;
3132
3233import java .util .ArrayList ;
3334import java .util .Collection ;
34- import java .util .Timer ;
35- import java .util .TimerTask ;
35+ import java .util .concurrent .Executors ;
36+ import java .util .concurrent .ScheduledExecutorService ;
37+ import java .util .concurrent .ScheduledFuture ;
38+ import java .util .concurrent .TimeUnit ;
3639
3740
3841/**
@@ -60,21 +63,21 @@ public abstract class AbstractWebSocket extends WebSocketAdapter {
6063 private boolean reuseAddr ;
6164
6265 /**
63- * Attribute for a timer allowing to check for lost connections
64- * @since 1.3.4
66+ * Attribute for a service that triggers lost connection checking
67+ * @since 1.4.1
6568 */
66- private Timer connectionLostTimer ;
69+ private ScheduledExecutorService connectionLostCheckerService ;
6770 /**
68- * Attribute for a timertask allowing to check for lost connections
69- * @since 1.3.4
71+ * Attribute for a task that checks for lost connections
72+ * @since 1.4.1
7073 */
71- private TimerTask connectionLostTimerTask ;
74+ private ScheduledFuture connectionLostCheckerFuture ;
7275
7376 /**
74- * Attribute for the lost connection check interval
77+ * Attribute for the lost connection check interval in nanoseconds
7578 * @since 1.3.4
7679 */
77- private int connectionLostTimeout = 60 ;
80+ private long connectionLostTimeout = TimeUnit . SECONDS . toNanos ( 60 ) ;
7881
7982 /**
8083 * Attribute to keep track if the WebSocket Server/Client is running/connected
@@ -89,12 +92,12 @@ public abstract class AbstractWebSocket extends WebSocketAdapter {
8992 /**
9093 * Get the interval checking for lost connections
9194 * Default is 60 seconds
92- * @return the interval
95+ * @return the interval in seconds
9396 * @since 1.3.4
9497 */
9598 public int getConnectionLostTimeout () {
9699 synchronized (syncConnectionLost ) {
97- return connectionLostTimeout ;
100+ return ( int ) TimeUnit . NANOSECONDS . toSeconds ( connectionLostTimeout ) ;
98101 }
99102 }
100103
@@ -107,7 +110,7 @@ public int getConnectionLostTimeout() {
107110 */
108111 public void setConnectionLostTimeout ( int connectionLostTimeout ) {
109112 synchronized (syncConnectionLost ) {
110- this .connectionLostTimeout = connectionLostTimeout ;
113+ this .connectionLostTimeout = TimeUnit . SECONDS . toNanos ( connectionLostTimeout ) ;
111114 if (this .connectionLostTimeout <= 0 ) {
112115 log .trace ("Connection lost timer stopped" );
113116 cancelConnectionLostTimer ();
@@ -139,7 +142,7 @@ public void setConnectionLostTimeout( int connectionLostTimeout ) {
139142 */
140143 protected void stopConnectionLostTimer () {
141144 synchronized (syncConnectionLost ) {
142- if (connectionLostTimer != null || connectionLostTimerTask != null ) {
145+ if (connectionLostCheckerService != null || connectionLostCheckerFuture != null ) {
143146 this .websocketRunning = false ;
144147 log .trace ("Connection lost timer stopped" );
145148 cancelConnectionLostTimer ();
@@ -168,8 +171,8 @@ protected void startConnectionLostTimer() {
168171 */
169172 private void restartConnectionLostTimer () {
170173 cancelConnectionLostTimer ();
171- connectionLostTimer = new Timer ( "WebSocketTimer" );
172- connectionLostTimerTask = new TimerTask () {
174+ connectionLostCheckerService = Executors . newSingleThreadScheduledExecutor ( new NamedThreadFactory ( "connectionLostChecker" ) );
175+ Runnable connectionLostChecker = new Runnable () {
173176
174177 /**
175178 * Keep the connections in a separate list to not cause deadlocks
@@ -180,31 +183,31 @@ public void run() {
180183 connections .clear ();
181184 try {
182185 connections .addAll ( getConnections () );
183- long current = ( System .currentTimeMillis () - ( connectionLostTimeout * 1500 ) );
186+ long minimumPongTime = (long ) ( System .nanoTime () - ( connectionLostTimeout * 1.5 ) );
184187 for ( WebSocket conn : connections ) {
185- executeConnectionLostDetection (conn , current );
188+ executeConnectionLostDetection (conn , minimumPongTime );
186189 }
187190 } catch ( Exception e ) {
188191 //Ignore this exception
189192 }
190193 connections .clear ();
191194 }
192195 };
193- connectionLostTimer .scheduleAtFixedRate ( connectionLostTimerTask ,1000L *connectionLostTimeout , 1000L *connectionLostTimeout );
194196
197+ connectionLostCheckerFuture = connectionLostCheckerService .scheduleAtFixedRate (connectionLostChecker , connectionLostTimeout , connectionLostTimeout , TimeUnit .NANOSECONDS );
195198 }
196199
197200 /**
198201 * Send a ping to the endpoint or close the connection since the other endpoint did not respond with a ping
199202 * @param webSocket the websocket instance
200- * @param current the current time in milliseconds
203+ * @param minimumPongTime the lowest/oldest allowable last pong time ( in nanoTime) before we consider the connection to be lost
201204 */
202- private void executeConnectionLostDetection (WebSocket webSocket , long current ) {
205+ private void executeConnectionLostDetection (WebSocket webSocket , long minimumPongTime ) {
203206 if (!(webSocket instanceof WebSocketImpl )) {
204207 return ;
205208 }
206209 WebSocketImpl webSocketImpl = (WebSocketImpl ) webSocket ;
207- if ( webSocketImpl .getLastPong () < current ) {
210+ if ( webSocketImpl .getLastPong () < minimumPongTime ) {
208211 log .trace ("Closing connection due to no pong received: {}" , webSocketImpl );
209212 webSocketImpl .closeConnection ( CloseFrame .ABNORMAL_CLOSE , "The connection was closed because the other endpoint did not respond with a pong in time. For more information check: https://github.com/TooTallNate/Java-WebSocket/wiki/Lost-connection-detection" );
210213 } else {
@@ -228,13 +231,13 @@ private void executeConnectionLostDetection(WebSocket webSocket, long current) {
228231 * @since 1.3.4
229232 */
230233 private void cancelConnectionLostTimer () {
231- if ( connectionLostTimer != null ) {
232- connectionLostTimer . cancel ();
233- connectionLostTimer = null ;
234+ if ( connectionLostCheckerService != null ) {
235+ connectionLostCheckerService . shutdownNow ();
236+ connectionLostCheckerService = null ;
234237 }
235- if ( connectionLostTimerTask != null ) {
236- connectionLostTimerTask .cancel ();
237- connectionLostTimerTask = null ;
238+ if ( connectionLostCheckerFuture != null ) {
239+ connectionLostCheckerFuture .cancel (false );
240+ connectionLostCheckerFuture = null ;
238241 }
239242 }
240243
0 commit comments