Skip to content

Commit 8ff3f4b

Browse files
author
Yegor Bugayenko
committed
#4 fixed
1 parent a74a038 commit 8ff3f4b

File tree

1 file changed

+37
-16
lines changed

1 file changed

+37
-16
lines changed

src/main/java/co/stateful/Atomic.java

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.Random;
3838
import java.util.concurrent.Callable;
3939
import java.util.concurrent.TimeUnit;
40+
import java.util.concurrent.atomic.AtomicBoolean;
4041
import lombok.EqualsAndHashCode;
4142
import lombok.ToString;
4243

@@ -70,13 +71,30 @@
7071
@Loggable(Loggable.DEBUG)
7172
@ToString
7273
@EqualsAndHashCode(of = { "callable", "lock" })
74+
@SuppressWarnings("PMD.DoNotUseThreads")
7375
public final class Atomic<T> implements Callable<T> {
7476

7577
/**
7678
* Random.
7779
*/
7880
private static final Random RANDOM = new SecureRandom();
7981

82+
/**
83+
* Shutdown hook.
84+
*/
85+
private final transient Thread hook = new Thread(
86+
new Runnable() {
87+
@Override
88+
public void run() {
89+
try {
90+
Atomic.this.lock.unlock();
91+
} catch (final IOException ex) {
92+
throw new IllegalStateException(ex);
93+
}
94+
}
95+
}
96+
);
97+
8098
/**
8199
* Callable to use.
82100
*/
@@ -92,6 +110,11 @@ public final class Atomic<T> implements Callable<T> {
92110
*/
93111
private final transient long max;
94112

113+
/**
114+
* Successfully locked?
115+
*/
116+
private final transient AtomicBoolean locked = new AtomicBoolean();
117+
95118
/**
96119
* Public ctor (default maximum waiting time of five minutes).
97120
* @param clbl Callable to use
@@ -115,21 +138,8 @@ public Atomic(final Callable<T> clbl, final Lock lck, final long maximum) {
115138
}
116139

117140
@Override
118-
@SuppressWarnings("PMD.DoNotUseThreads")
119141
public T call() throws Exception {
120-
final Thread hook = new Thread(
121-
new Runnable() {
122-
@Override
123-
public void run() {
124-
try {
125-
Atomic.this.lock.unlock();
126-
} catch (final IOException ex) {
127-
throw new IllegalStateException(ex);
128-
}
129-
}
130-
}
131-
);
132-
Runtime.getRuntime().addShutdownHook(hook);
142+
Runtime.getRuntime().addShutdownHook(this.hook);
133143
long attempt = 0L;
134144
final long start = System.currentTimeMillis();
135145
while (!this.lock.lock()) {
@@ -157,11 +167,11 @@ public void run() {
157167
);
158168
TimeUnit.MILLISECONDS.sleep(delay);
159169
}
170+
this.locked.set(true);
160171
try {
161172
return this.callable.call();
162173
} finally {
163-
this.lock.unlock();
164-
Runtime.getRuntime().removeShutdownHook(hook);
174+
this.unlock();
165175
}
166176
}
167177

@@ -180,4 +190,15 @@ public T callQuietly() {
180190
}
181191
}
182192

193+
/**
194+
* Unlock it.
195+
* @throws IOException If fails
196+
*/
197+
private void unlock() throws IOException {
198+
if (this.locked.get()) {
199+
this.lock.unlock();
200+
}
201+
Runtime.getRuntime().removeShutdownHook(this.hook);
202+
}
203+
183204
}

0 commit comments

Comments
 (0)