11/*
2- * Copyright (c) 2000, 2020 , Oracle and/or its affiliates.
2+ * Copyright (c) 2000, 2025 , Oracle and/or its affiliates.
33 *
44 * Licensed under the Universal Permissive License v 1.0 as shown at
5- * http ://oss.oracle.com/licenses/upl.
5+ * https ://oss.oracle.com/licenses/upl.
66 */
77
88package com .tangosol .net ;
99
1010
1111import com .tangosol .coherence .config .Config ;
1212
13+ import com .tangosol .internal .util .VirtualThreads ;
14+
1315import com .tangosol .util .Base ;
14- import com .tangosol .util .Daemon ;
1516
1617import java .net .InetSocketAddress ;
1718
1819import java .util .ArrayList ;
1920import java .util .Iterator ;
2021import java .util .List ;
2122
23+ import java .util .concurrent .Executor ;
24+ import java .util .concurrent .locks .Lock ;
25+ import java .util .concurrent .locks .ReentrantLock ;
26+
2227
2328/**
2429* A RefreshableAddressProvider is an AddressProvider implementation
@@ -57,7 +62,9 @@ public RefreshableAddressProvider(AddressProvider ap, long lRefresh)
5762 // populate the initial address list cache
5863 refreshAddressList ();
5964 // initialize the refresh thread
60- f_daemonRefresh = new RefreshThread (lRefresh );
65+ String sName = RefreshableAddressProvider .this .getClass ().getName () + ": RefreshThread" ;
66+ f_refreshTask = new RefreshTask (lRefresh );
67+ f_daemonRefresh = VirtualThreads .newMaybeVirtualThreadExecutor (r -> new Thread (r , sName ));
6168 }
6269
6370 /**
@@ -178,54 +185,74 @@ protected void refreshAddressList()
178185 */
179186 protected void ensureRefreshThread ()
180187 {
181- if (!f_daemonRefresh .isRunning ())
188+ if (!f_refreshTask .isRunning ())
182189 {
183- f_daemonRefresh .start ( );
190+ f_daemonRefresh .execute ( f_refreshTask );
184191 }
185192 }
186193
187194
188195 // ----- inner class: RefreshThread -------------------------------------
189196
190- protected class RefreshThread
191- extends Daemon
197+ protected class RefreshTask
198+ implements Runnable
192199 {
193200 // ----- constructors -----------------------------------------------
194201
195202 /**
196- * Construct a new RefreshThread with the specified refresh interval.
203+ * Construct a new RefreshTask with the specified refresh interval.
197204 *
198205 * @param lRefresh the refresh interval
199206 */
200- protected RefreshThread (long lRefresh )
207+ protected RefreshTask (long lRefresh )
201208 {
202- super (RefreshableAddressProvider .this .getClass ().getName () +
203- ": RefreshThread" );
204209 f_lRefresh = lRefresh ;
205210 }
206211
207- /**
208- * {@inheritDoc}
209- */
212+ public boolean isRunning ()
213+ {
214+ return m_fRunning ;
215+ }
216+
217+ @ Override
210218 public void run ()
211219 {
212- long lRefresh = f_lRefresh ;
213- while (!isStopping ())
220+ if (m_fRunning )
214221 {
215- try
216- {
217- refreshAddressList ();
218- stop ();
219- }
220- catch (Throwable t )
222+ return ;
223+ }
224+
225+ f_lock .lock ();
226+ try
227+ {
228+ if (!m_fRunning )
221229 {
222- err ("An exception occurred while refreshing an address list: " +
223- "\n " + getStackTrace (t ) +
224- "\n Reducing the refresh rate." );
225- Base .sleep (lRefresh );
226- lRefresh = 2 * lRefresh ;
230+ m_fRunning = true ;
231+ long lRefresh = f_lRefresh ;
232+ while (m_fRunning )
233+ {
234+ try
235+ {
236+ refreshAddressList ();
237+ m_fRunning = false ;
238+ }
239+ catch (Throwable t )
240+ {
241+ err ("An exception occurred while refreshing an address list: " +
242+ "\n " + t .getMessage () +
243+ "\n " + getStackTrace (t ) +
244+ "\n Reducing the refresh rate." );
245+ Base .sleep (lRefresh );
246+ lRefresh = 2 * lRefresh ;
247+ }
248+ }
227249 }
228250 }
251+ finally
252+ {
253+ m_fRunning = false ;
254+ f_lock .unlock ();
255+ }
229256 }
230257
231258 // ----- data members -----------------------------------------------
@@ -234,6 +261,16 @@ public void run()
234261 * The interval with which to attempt to refresh the address list.
235262 */
236263 protected final long f_lRefresh ;
264+
265+ /**
266+ * The flag to indicate whether the task is running.
267+ */
268+ private volatile boolean m_fRunning = false ;
269+
270+ /**
271+ * A lock to control running only a single task.
272+ */
273+ private final Lock f_lock = new ReentrantLock ();
237274 }
238275
239276
@@ -357,7 +394,15 @@ protected void refreshIterator()
357394 /**
358395 * The refresh daemon.
359396 */
360- protected final Daemon f_daemonRefresh ;
397+ protected final RefreshTask f_refreshTask ;
398+
399+ /**
400+ * The refresh executor.
401+ * <p>
402+ * This will be a single threaded executor on Java 17 or a
403+ * virtual thread per-task on Java 21 or higher.
404+ */
405+ protected final Executor f_daemonRefresh ;
361406
362407 /**
363408 * An Iterator over the cached set of addresses.
0 commit comments