Skip to content

Commit c7fd667

Browse files
authored
Fix thread leak (#16)
1 parent f0b5280 commit c7fd667

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

src/main/java/de/labystudio/spotifyapi/SpotifyAPI.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ default SpotifyAPI initialize() {
3636
*/
3737
SpotifyAPI initialize(SpotifyConfiguration configuration);
3838

39-
4039
/**
4140
* Initialize the SpotifyAPI and connect to the Spotify process asynchronously.
4241
*
@@ -47,7 +46,6 @@ default CompletableFuture<SpotifyAPI> initializeAsync(SpotifyConfiguration confi
4746
return CompletableFuture.supplyAsync(() -> this.initialize(configuration));
4847
}
4948

50-
5149
/**
5250
* Initialize the SpotifyAPI and connect to the Spotify process asynchronously.
5351
* It will use a default configuration.
@@ -119,7 +117,6 @@ default boolean hasTrack() {
119117
*/
120118
boolean isConnected();
121119

122-
123120
/**
124121
* Returns true if the background process is running.
125122
*
@@ -154,4 +151,11 @@ default boolean hasTrack() {
154151
* Disconnect from the Spotify application and stop all background tasks.
155152
*/
156153
void stop();
154+
155+
/**
156+
* Similar to {@link SpotifyAPI#stop()} but releases any held resources.
157+
* <p>
158+
* Should only be called if there is no intent to reuse this instance.
159+
*/
160+
void shutdown();
157161
}

src/main/java/de/labystudio/spotifyapi/platform/AbstractTickSpotifyAPI.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.ArrayList;
99
import java.util.List;
1010
import java.util.concurrent.Executors;
11+
import java.util.concurrent.ScheduledExecutorService;
1112
import java.util.concurrent.ScheduledFuture;
1213
import java.util.concurrent.TimeUnit;
1314

@@ -27,33 +28,34 @@ public abstract class AbstractTickSpotifyAPI implements SpotifyAPI {
2728

2829
private SpotifyConfiguration configuration;
2930

31+
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
32+
3033
private ScheduledFuture<?> task;
34+
3135
private long timeLastException = -1;
3236

3337
/**
3438
* Initialize the SpotifyAPI abstract tick implementation.
3539
* It will create a task that will update the current track and position every second.
3640
*
3741
* @return the initialized SpotifyAPI
38-
* @throws IllegalStateException if the API is already initialized
42+
* @throws IllegalStateException if the API is already initialized or has been shutdown
3943
*/
4044
@Override
4145
public SpotifyAPI initialize(SpotifyConfiguration configuration) {
4246
synchronized (this) {
4347
this.configuration = configuration;
4448

49+
if (this.executor.isShutdown()) {
50+
throw new IllegalStateException("This SpotifyAPI has been shutdown and cannot be reused");
51+
}
52+
4553
if (this.isInitialized()) {
46-
throw new IllegalStateException("The SpotifyAPI is already initialized");
54+
throw new IllegalStateException("This SpotifyAPI is already initialized");
4755
}
4856

4957
// Start task to update every second
50-
this.task = Executors.newScheduledThreadPool(1)
51-
.scheduleWithFixedDelay(
52-
this::onInternalTick,
53-
0,
54-
1,
55-
TimeUnit.SECONDS
56-
);
58+
this.task = this.executor.scheduleWithFixedDelay(this::onInternalTick, 0L, 1L, TimeUnit.SECONDS);
5759
}
5860
return this;
5961
}
@@ -120,4 +122,10 @@ public void stop() {
120122
}
121123
}
122124
}
125+
126+
@Override
127+
public void shutdown() {
128+
this.stop();
129+
this.executor.shutdownNow();
130+
}
123131
}

0 commit comments

Comments
 (0)