1414import java .time .format .DateTimeFormatter ;
1515import java .time .temporal .ChronoUnit ;
1616import java .util .*;
17+ import java .util .concurrent .atomic .AtomicReference ;
1718import java .util .function .Consumer ;
1819import java .util .logging .Logger ;
1920
@@ -52,10 +53,8 @@ abstract class GitHubClient {
5253
5354 private HttpConnector connector ;
5455
55- private final Object rateLimitLock = new Object ();
56-
5756 @ Nonnull
58- private GHRateLimit rateLimit = GHRateLimit .DEFAULT ;
57+ private final AtomicReference < GHRateLimit > rateLimit = new AtomicReference <>( GHRateLimit .DEFAULT ) ;
5958
6059 private static final Logger LOGGER = Logger .getLogger (GitHubClient .class .getName ());
6160
@@ -255,9 +254,7 @@ GHRateLimit getRateLimit(@Nonnull RateLimitTarget rateLimitTarget) throws IOExce
255254 @ Nonnull
256255 @ Deprecated
257256 GHRateLimit lastRateLimit () {
258- synchronized (rateLimitLock ) {
259- return rateLimit ;
260- }
257+ return rateLimit .get ();
261258 }
262259
263260 /**
@@ -277,12 +274,19 @@ GHRateLimit lastRateLimit() {
277274 */
278275 @ Nonnull
279276 GHRateLimit rateLimit (@ Nonnull RateLimitTarget rateLimitTarget ) throws IOException {
280- synchronized (rateLimitLock ) {
281- if (rateLimit .getRecord (rateLimitTarget ).isExpired ()) {
282- getRateLimit (rateLimitTarget );
277+ GHRateLimit result = rateLimit .get ();
278+ // Most of the time rate limit is not expired, so try to avoid locking.
279+ if (result .getRecord (rateLimitTarget ).isExpired ()) {
280+ // if the rate limit is expired, synchronize to ensure
281+ // only one call to getRateLimit() is made to refresh it.
282+ synchronized (this ) {
283+ if (rateLimit .get ().getRecord (rateLimitTarget ).isExpired ()) {
284+ getRateLimit (rateLimitTarget );
285+ }
283286 }
284- return rateLimit ;
287+ result = rateLimit . get () ;
285288 }
289+ return result ;
286290 }
287291
288292 /**
@@ -295,15 +299,9 @@ GHRateLimit rateLimit(@Nonnull RateLimitTarget rateLimitTarget) throws IOExcepti
295299 * {@link GHRateLimit.Record} constructed from the response header information
296300 */
297301 private GHRateLimit updateRateLimit (@ Nonnull GHRateLimit observed ) {
298- synchronized (rateLimitLock ) {
299- observed = rateLimit .getMergedRateLimit (observed );
300-
301- if (rateLimit != observed ) {
302- rateLimit = observed ;
303- LOGGER .log (FINE , "Rate limit now: {0}" , rateLimit );
304- }
305- return rateLimit ;
306- }
302+ GHRateLimit result = rateLimit .accumulateAndGet (observed , (current , x ) -> current .getMergedRateLimit (x ));
303+ LOGGER .log (FINEST , "Rate limit now: {0}" , rateLimit .get ());
304+ return result ;
307305 }
308306
309307 /**
0 commit comments