Home > OS >  Usage of parallelStream() resulting in unclosed Threads?
Usage of parallelStream() resulting in unclosed Threads?

Time:11-20

I'm writing a rss media grabber and one of my parallelStream()s is resulting in unclosed threads.

They are all Daemon Thread [ForkJoinPool.commonPool-worker-xx] threads.

The only difference I could spot was that both examples are invoked from different threads. Could this be the problem? Even when I tried starting a new Thread().start, the parallelStream() left all ForkJoinPool threads unclosed behind. And I also tried using simple objects like ArrayList<int> with the same outcome. Is this a wanted behavior outside the main thread?

Or is it just the behavior described in the docs(bold part):

A ForkJoinPool differs from other kinds of ExecutorService mainly by virtue of employing work-stealing: all threads in the pool attempt to find and execute tasks submitted to the pool and/or created by other active tasks (eventually blocking waiting for work if none exist).

public class MainRoutine {
    
    public static void startRoutine(SubReddit subReddit) {
        ArrayList<Entry> rssEntry = RSSgrab.pullRss(new SubReddit("pics", true, null));
        
        rssEntry.parallelStream().forEach(System.out::println); //produces unclosed threads
        System.out.println(Thread.currentThread().getName()); //prints AWT-EventQueue-0
    }

    public static void main(String[] args) {
        ArrayList<Entry> rssEntry = RSSgrab.pullRss(new SubReddit("pics", true, null));
        
        rssEntry.parallelStream().forEach(System.out::println); //this does not produce unclosed threads
        System.out.println(Thread.currentThread().getName()); //prints main
    //my bad, does also produce unclosed threads but the runtime is so short that I did not notice ofc
    }

}

Entry class

public class Entry {
    String user;
    String userUri;
    String id;
    String uri;
    String date;
    String title;
    
    private ArrayList<String> media = new ArrayList<String>();
    
    public Entry(String user, String userUri, String id, String uri, String date, String title) {
        this.user = user;
        this.userUri = userUri;
        this.id = id;
        this.uri = uri;
        this.date = date;
        this.title = title;
    }

    @Override
    public String toString() {
        return "Entry [user="   user   ", userUri="   userUri   ", id="   id   ", uri="   uri   ", date="   date
                  ", title="   title   ", media=" getMedia().stream().map(s -> s "; ").reduce("", String::concat) "]";
    }

    public ArrayList<String> getMedia() {
        return media;
    }

    public void setMedia(ArrayList<String> media) {
        this.media = media;
    }
}

enter image description here

CodePudding user response:

Basically ... you are trying to solve a problem that isn't a problem. The common fork-join pool is a managed pool. The JVM takes care of it.

And if it really matters to you, the bad news is that there is probably nothing you can do about it. The common pool will ignore shutdown() and shutdownNow() calls. This is by design.

There is a trick which allows you to create a custom ForkJoinPool and run your stream in it. See Custom thread pool in Java 8 parallel stream. Once you are finished you can shutdown the pool to make the threads go away.

But ... it is probably a bad idea. It is more efficient to reuse an existing pool or the common pool. Creating and destroying threads is expensive. Doing this repeatedly because you are repeatedly creating and destroying pools is inefficient.

The common ForkJoinPool should not be viewed as a thread leak.

  • Related