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{
6063private 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 */
9598public int getConnectionLostTimeout (){
9699synchronized (syncConnectionLost ){
97- return connectionLostTimeout ;
100+ return ( int ) TimeUnit . NANOSECONDS . toSeconds ( connectionLostTimeout ) ;
98101 }
99102 }
100103
@@ -107,7 +110,7 @@ public int getConnectionLostTimeout(){
107110 */
108111public void setConnectionLostTimeout ( int connectionLostTimeout ){
109112synchronized (syncConnectionLost ){
110- this .connectionLostTimeout = connectionLostTimeout ;
113+ this .connectionLostTimeout = TimeUnit . SECONDS . toNanos ( connectionLostTimeout ) ;
111114if (this .connectionLostTimeout <= 0 ){
112115log .trace ("Connection lost timer stopped" );
113116cancelConnectionLostTimer ();
@@ -139,7 +142,7 @@ public void setConnectionLostTimeout( int connectionLostTimeout ){
139142 */
140143protected void stopConnectionLostTimer (){
141144synchronized (syncConnectionLost ){
142- if (connectionLostTimer != null || connectionLostTimerTask != null ){
145+ if (connectionLostCheckerService != null || connectionLostCheckerFuture != null ){
143146this .websocketRunning = false ;
144147log .trace ("Connection lost timer stopped" );
145148cancelConnectionLostTimer ();
@@ -168,8 +171,8 @@ protected void startConnectionLostTimer(){
168171 */
169172private void restartConnectionLostTimer (){
170173cancelConnectionLostTimer ();
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(){
180183connections .clear ();
181184try {
182185connections .addAll ( getConnections () );
183- long current = (System .currentTimeMillis () - ( connectionLostTimeout * 1500 ) );
186+ long minimumPongTime = (long ) ( System .nanoTime () - ( connectionLostTimeout * 1.5 ) );
184187for ( WebSocket conn : connections ){
185- executeConnectionLostDetection (conn , current );
188+ executeConnectionLostDetection (conn , minimumPongTime );
186189 }
187190 } catch ( Exception e ){
188191//Ignore this exception
189192 }
190193connections .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 ){
203206if (!(webSocket instanceof WebSocketImpl )){
204207return ;
205208 }
206209WebSocketImpl webSocketImpl = (WebSocketImpl ) webSocket ;
207- if ( webSocketImpl .getLastPong () < current ){
210+ if ( webSocketImpl .getLastPong () < minimumPongTime ){
208211log .trace ("Closing connection due to no pong received:{}" , webSocketImpl );
209212webSocketImpl .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 */
230233private 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