3

How can I make Callable thread as daemon thread?

Here is what I am trying. I am trying to execute a set of threads of which one of them does not complete and goes into infinite loop. What it does is the main thread of the program does not terminate even though all the code statements are executed. The main thread goes into suspended mode after that.

Here is the code snippet for the same.

public class MyThread implements Callable<String> {

    private int value;

    public MyThread(int value) {
        this.value = value;
    }

    @Override
    public String call() throws Exception {

        //Thread.currentThread().setDaemon(true);

        System.out.println("Executing - " + value);

        if (value == 4) {
            for (; ; );
        }

        return value + "";
    }
}

Main Program

public class ExecutorMain {

    public static String testing() {    
        ExecutorService executor = null;
        List<Future<String>> result = null;
        String parsedValue = null;
        try {
            executor = Executors.newSingleThreadExecutor();

            List<MyThread> threads = new ArrayList<MyThread>();

            for (int i = 1; i < 10; i++) {
                MyThread obj = new MyThread(i);
                threads.add(obj);
            }

            result = executor.invokeAll(threads, Long.valueOf("4000"), TimeUnit.MILLISECONDS);
            //result = executor.invokeAll(threads);

            for (Future<String> f : result) {
                try {
                    parsedValue = f.get();
                    System.out.println("Return Value - " + parsedValue);
                } catch (CancellationException e) {
                    System.out.println("Cancelled");
                    parsedValue = "";
                    f.cancel(true);
                }
            }

            executor.shutdownNow();
        } catch (Exception e) {
            System.out.println("Exception while running threads");
            e.printStackTrace();
        } finally {
            List executedThreads = executor.shutdownNow();

            System.out.println(executedThreads);

            for (Object o : executedThreads) {
                System.out.println(o.getClass());
            }
        }
        System.out.println("Exiting....");
        //System.exit(1);

        return "";
    }

    public static void main(String[] args) {
        testing();
    }
}

What I got to understand from my earlier question about Dangling threads in Java is that I have to make my threads as daemon threads.

Community
  • 1
  • 1
divinedragon
  • 5,105
  • 13
  • 50
  • 97

4 Answers4

8

How can I make Callable thread as daemon thread?

You need to use a new ThreadFactory that creates daemon threads. See this answer here: Executor and Daemon in Java

By default the executors create non-daemon threads whenever they build their pools. But you can inject your own ThreadFactory which creates the threads for the pool.

For example:

executor = ExecutorService.newSingleThreadExecutor(new MyThreadFactory());

The ThreadFactory implements the newThread method:

Thread newThread(Runnable r)

Copied from the answer I linked to above, you could implement it like:

class MyThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        thread.setDaemon(true);
        return thread;
    }
}

You mentioned in your question:

//Thread.currentThread().setDaemon(true);

Yeah, this won't work because you cannot set the daemon flag once the thread has been started.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • Strange - we just had a little discussion about defaults. This is the sort of stuff that happens when the default app shutdown functionality is 'don't' :) – Martin James Apr 05 '12 at 14:58
4

It is not about making Callable to daemon. You actually want to make the execute threads become daemon. You can create the thread in this way to make it becomes daemon:

executor = Executors.newSingleThreadExecutor(new ThreadFactory(){
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }        
});
evanwong
  • 5,054
  • 3
  • 31
  • 44
0

Just setting the Threads created by the ExecutorService to daemon won't help (though you do need to do this). You can set your ExecutorService Threads to daemon like so:

executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }        
});

The real problem you are having is with this code block:

        for (Future<String> f : result) {
            try {
                parsedValue = f.get();
                System.out.println("Return Value - " + parsedValue);
            } catch (CancellationException e) {
                System.out.println("Cancelled");
                parsedValue = "";
                f.cancel(true);
            }
        }

        executor.shutdownNow();

More specifically, this code will hang forever here:

parsedValue = f.get();

The reason for this is simple, the Future#get method "Waits if necessary for the computation to complete, and then retrieves its result.", but the computation will never complete because it is in an infinite loop. Not even an interrupt from ThreadPoolExecutor#shutdownNow or Future#cancel(true) will help you because your Callable code is not perofrming a blocking operation or otherwise checking for an interrupt.

From here, you have two options:

  1. Use the form of Future#get that takes a long timeout argument.
  2. Use Future#isDone to determine if the Future#get method has a value to return prior to actually calling Future#get.
Tim Bender
  • 20,112
  • 2
  • 49
  • 58
  • Thanks Tim for the detailed explanation. However, your proposed solution did not solve the issue. The problem was that because the thread has gone to infinite loop, it does not check for any thread interruption and hence does not terminate. – divinedragon Apr 06 '12 at 13:12
  • Right,,, which isn't a problem as long as it is daemon and you do not block a non-daemon thread waiting for it to complete. I mentioned the issue with not checking for an interrupt. Either way, I'm glad you figured it out. This stuff is important! :-) – Tim Bender Apr 06 '12 at 16:09
0

Thanks Tim for the detailed explanation. However, your proposed solution did not solve the issue. The problem was that because the thread has gone to infinite loop, it does not check for any thread interruption and hence does not terminate.

For my scenario, infinite loop is not a good example, but what we were trying to accomplish is that we were executing a regular expression which was taking too long to execute and the check for interruption was after matcher.find() call. Because find() does not return in stipulated time and also the find() method does not check for thread interruptions, we were facing the dangling thread issue. Finally, implemented InterruptableCharSequence from this url and got it working.

Community
  • 1
  • 1
divinedragon
  • 5,105
  • 13
  • 50
  • 97
  • You are adding extraneous unpublished details *after the fact*. Some of the other answers addressed the OP properly. Instead of creating a new answer , maybe add this as an update to the OP. After all - the reason Tim's solution "did not solve" the issue is because your "issue" did not match the OP description. That is an incorrect formulation of the OP - but does not detract from the correctness of *his* answer. – WestCoastProjects Aug 09 '15 at 17:02