HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Code organization when using threads

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
threadsusingwhencodeorganization

Problem

From OOP & OOD point of view, is it good idea to define Java-threads inside of the static method or in this case it's better to use instance-based method?

public class ThreadPool {

    public static void stringAnalysis(ArrayList strData) {
        Thread t;
        t = new Thread(new SentimentAnalysis(strData));
        t.start();
    }
}

public class SentimentAnalysis implements Runnable {

    private ArrayList strData;

    public SentimentAnalysis(ArrayList strData) {
        this.strData = strData;
    }

    public void computeSentiment(ArrayList strData) {
        StanfordNLP_forked.analyze(strData);
    }

    public void run() {
        this.computeSentiment(strData);
    }
}


StanfordNLP_forked is a forked version of StanfordCoreNLP for educational purpose only. StanfordNLP_forked.analyze(strData) performs text analysis of the strings array and replace each string with sentimental rank value. For the moment, I just check in the debugger the result of the analysis, later I'll add some functionality.

Solution

The Best-practice threading policy in Java is now to use the ExecutorService implementations found in the java.util.concurrent package.

Before we go there, though, your current code should be improved. The method:

public static void stringAnalysis(ArrayList strData) {
    Thread t;
    t = new Thread(new SentimentAnalysis(strData));
    t.start();
}


creates and starts a thread. The thread that is started is a regular thread, as opposed to a daemon thread. The JVM will exit when all threads complete, or all the remaining threads are Daemon (background) threads: see Thread.setDaemon(boolean).

You should typically use Daemon threads (and I believe that Java has a bug in that Daemon threads should be the default).

Additionally, there is no reason to 'Declare' the t Thread variable before assigning to it.

Finally, for many reasons, it is nice to give threads names.

I would have the code:

public static void stringAnalysis(ArrayList strData) {
    Thread toRun = new Thread(new SentimentAnalysis(strData), "Sentiment Analysis thread");
    toRun.setDaemon(true);
    toRun.start();
}


But, in reality, I would use an Executor service....
Executors.

Executor services work best with Daemon threads too. Here's a method that creates a Daemon thread for an Executor service:

private static final AtomicInteger sentimentThreadID = new AtomicInteger();

public static Thread createSentimentThread(Runnable toRun) {
    String name = "Sentiment Thread " + sentimentThreadID.incrementAndGet();
    Thread myThread = new Thread(toRun, name);
    myThread.setDaemon(true);
    return myThread();
}


Executors have their own Runnable that they use to create the thread. When you have your runnable, you pass it to the Executor, and the Executor runs it on one of the Executor's threads.

So, you can create an ExecutorService with something like (using Java 8):

ExecutorService sentimentService = Executors.newCachedThreadPool(
        runnable -> createSentimentThread(runnable)
    );


Java 7 would be slightly longer with:

ThreadFactory factory = new ThreadFactory() {
   @Override
   public Thread newThread(Runnable r) {
     return createSentimentThread(r);
   }

};
ExecutorService sentimentService = Executors.newCachedThreadPool(factory);


Once you have the sentimentService, you can run your analysis Runnables with:

sentimentService.submit(new SentimentAnalysis(strData));

Code Snippets

public static void stringAnalysis(ArrayList<String> strData) {
    Thread t;
    t = new Thread(new SentimentAnalysis(strData));
    t.start();
}
public static void stringAnalysis(ArrayList<String> strData) {
    Thread toRun = new Thread(new SentimentAnalysis(strData), "Sentiment Analysis thread");
    toRun.setDaemon(true);
    toRun.start();
}
private static final AtomicInteger sentimentThreadID = new AtomicInteger();

public static Thread createSentimentThread(Runnable toRun) {
    String name = "Sentiment Thread " + sentimentThreadID.incrementAndGet();
    Thread myThread = new Thread(toRun, name);
    myThread.setDaemon(true);
    return myThread();
}
ExecutorService sentimentService = Executors.newCachedThreadPool(
        runnable -> createSentimentThread(runnable)
    );
ThreadFactory factory = new ThreadFactory() {
   @Override
   public Thread newThread(Runnable r) {
     return createSentimentThread(r);
   }

};
ExecutorService sentimentService = Executors.newCachedThreadPool(factory);

Context

StackExchange Code Review Q#71674, answer score: 2

Revisions (0)

No revisions yet.