Skip to content

Commit

Permalink
OPENNLP-1620 - It should be possible to remove the allocated ThreadLocal
Browse files Browse the repository at this point in the history
  • Loading branch information
rzo1 committed Oct 17, 2024
1 parent c01b362 commit ccca8ca
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,18 @@
/**
* A thread-safe version of the POSTaggerME. Using it is completely transparent. You can use it in
* a single-threaded context as well, it only incurs a minimal overhead.
* <p>
* Note, however, that this implementation uses a {@link ThreadLocal}. Although the implementation is
* lightweight because the model is not duplicated, if you have many long-running threads,
* you may run into memory problems.
* </p>
* <p>
* Be careful when using this in a Jakarta EE application, for example.
* </p>
* The user is responsible for clearing the {@link ThreadLocal}.
*/
@ThreadSafe
public class ThreadSafePOSTaggerME implements POSTagger {
public class ThreadSafePOSTaggerME implements POSTagger, AutoCloseable {

private final POSModel model;

Expand Down Expand Up @@ -64,4 +73,9 @@ public Sequence[] topKSequences(String[] sentence) {
public Sequence[] topKSequences(String[] sentence, Object[] additionaContext) {
return getTagger().topKSequences(sentence, additionaContext);
}

@Override
public void close() {
threadLocal.remove();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,21 @@
* A thread-safe version of SentenceDetectorME. Using it is completely transparent. You can use it in
* a single-threaded context as well, it only incurs a minimal overhead.
* <p>
* Note, however, that this implementation uses a ThreadLocal. Although the implementation is
* lightweight as the model is not duplicated, if you have many long-running threads, you may run
* into memory issues. Be careful when you use this in a JEE application, for example.
* Note, however, that this implementation uses a {@link ThreadLocal}. Although the implementation is
* lightweight because the model is not duplicated, if you have many long-running threads,
* you may run into memory problems.
* </p>
* <p>
* Be careful when using this in a Jakarta EE application, for example.
* </p>
* The user is responsible for clearing the {@link ThreadLocal}.
*/
@ThreadSafe
public class ThreadSafeSentenceDetectorME implements SentenceDetector {
public class ThreadSafeSentenceDetectorME implements SentenceDetector, AutoCloseable {

private final SentenceModel model;

private final ThreadLocal<SentenceDetectorME> sentenceDetectorThreadLocal =
private final ThreadLocal<SentenceDetectorME> threadLocal =
new ThreadLocal<>();

public ThreadSafeSentenceDetectorME(SentenceModel model) {
Expand All @@ -43,10 +48,10 @@ public ThreadSafeSentenceDetectorME(SentenceModel model) {

// If a thread-local version exists, return it. Otherwise, create, then return.
private SentenceDetectorME getSD() {
SentenceDetectorME sd = sentenceDetectorThreadLocal.get();
SentenceDetectorME sd = threadLocal.get();
if (sd == null) {
sd = new SentenceDetectorME(model);
sentenceDetectorThreadLocal.set(sd);
threadLocal.set(sd);
}
return sd;
}
Expand All @@ -64,4 +69,9 @@ public String[] sentDetect(CharSequence s) {
public Span[] sentPosDetect(CharSequence s) {
return getSD().sentPosDetect(s);
}

@Override
public void close() {
threadLocal.remove();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,33 @@
/**
* A thread-safe version of TokenizerME. Using it is completely transparent. You can use it in
* a single-threaded context as well, it only incurs a minimal overhead.
* <p>
* Note, however, that this implementation uses a {@link ThreadLocal}. Although the implementation is
* lightweight because the model is not duplicated, if you have many long-running threads,
* you may run into memory problems.
* </p>
* <p>
* Be careful when using this in a Jakarta EE application, for example.
* </p>
* The user is responsible for clearing the {@link ThreadLocal}.
*/
@ThreadSafe
public class ThreadSafeTokenizerME implements Tokenizer {
public class ThreadSafeTokenizerME implements Tokenizer, AutoCloseable {

private final TokenizerModel model;

private final ThreadLocal<TokenizerME> tokenizerThreadLocal = new ThreadLocal<>();
private final ThreadLocal<TokenizerME> threadLocal = new ThreadLocal<>();

public ThreadSafeTokenizerME(TokenizerModel model) {
super();
this.model = model;
}

private TokenizerME getTokenizer() {
TokenizerME tokenizer = tokenizerThreadLocal.get();
TokenizerME tokenizer = threadLocal.get();
if (tokenizer == null) {
tokenizer = new TokenizerME(model);
tokenizerThreadLocal.set(tokenizer);
threadLocal.set(tokenizer);
}
return tokenizer;
}
Expand All @@ -58,4 +67,9 @@ public Span[] tokenizePos(String s) {
public double[] getProbabilities() {
return getTokenizer().getTokenProbabilities();
}

@Override
public void close() {
threadLocal.remove();
}
}

0 comments on commit ccca8ca

Please sign in to comment.