You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by George Christman <gc...@cardaddy.com> on 2015/07/08 19:59:47 UTC

Multi threading in a service

I'm wondering what the best approach would be to handle multi threading in
a service so that I have other service classes available to me.

I'm passing in PDFService, but I'd like to pass it in through constructor
injection.

I'm assuming I'd have to instantiate the pool within archiveQueue and not
set a class variable followed by me binding WorkQueue to an interface? I

Current Code

public class WorkQueue {

    private final ExecutorService pool;

    private final PDFService pdfService;

    public WorkQueue(PDFService pdfService, int poolSize) {
        this.pdfService = pdfService;
        this.pool = Executors.newFixedThreadPool(poolSize);
    }

    public void archiveQueue(List<TimeSheet> timeSheets) {
        try {
            for (final TimeSheet timeSheet : timeSheets) {
                pool.execute(new Runnable() {
                    @Override
                    public void run() {
                        pdfService.generatePDF(null, timeSheet);
                    }
                });
            }
        } catch (Exception ex) {
            Logger.getLogger(WorkQueue.class.getName()).log(Level.SEVERE,
null, ex);
        }
    }

    void shutdownAndAwaitTermination(ExecutorService pool) {
        pool.shutdown(); // Disable new tasks from being submitted
        try {
            // Wait a while for existing tasks to terminate
            if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                pool.shutdownNow(); // Cancel currently executing tasks
                // Wait a while for tasks to respond to being cancelled
                if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                    System.err.println("Pool did not terminate");
                }
            }
        } catch (InterruptedException ie) {
            // (Re-)Cancel if current thread also interrupted
            pool.shutdownNow();
            // Preserve interrupt status
            Thread.currentThread().interrupt();
        }
    }

}

Re: Multi threading in a service

Posted by Lance Java <la...@googlemail.com>.
Seems like you're currently instantiating a WorkQueue calling
archiveQueue() then calling shutdownAndAwaitTermination() and discarding
the WorkQueue... Correct?

If you use ExecutorService.submit() instead of ExecutorService.execute()
you can call use the Future response and call Future.get() later to wait
for the work to finish.

I think if you refactored like this, WorkQueue could become a singleton and
you could probably get rid of shutdownAndAwaitTermination() all together.

Also, for any threading in tapestry, it's always best to @Inject
PerThreadManager and call cleanupThread() in a finally block of the
runnable (or use ParallelExecutor which does this for you). This will
cleanup any per thread values (eg hibernate session etc).
On 8 Jul 2015 19:01, "George Christman" <gc...@cardaddy.com> wrote:

> I'm wondering what the best approach would be to handle multi threading in
> a service so that I have other service classes available to me.
>
> I'm passing in PDFService, but I'd like to pass it in through constructor
> injection.
>
> I'm assuming I'd have to instantiate the pool within archiveQueue and not
> set a class variable followed by me binding WorkQueue to an interface? I
>
> Current Code
>
> public class WorkQueue {
>
>     private final ExecutorService pool;
>
>     private final PDFService pdfService;
>
>     public WorkQueue(PDFService pdfService, int poolSize) {
>         this.pdfService = pdfService;
>         this.pool = Executors.newFixedThreadPool(poolSize);
>     }
>
>     public void archiveQueue(List<TimeSheet> timeSheets) {
>         try {
>             for (final TimeSheet timeSheet : timeSheets) {
>                 pool.execute(new Runnable() {
>                     @Override
>                     public void run() {
>                         pdfService.generatePDF(null, timeSheet);
>                     }
>                 });
>             }
>         } catch (Exception ex) {
>             Logger.getLogger(WorkQueue.class.getName()).log(Level.SEVERE,
> null, ex);
>         }
>     }
>
>     void shutdownAndAwaitTermination(ExecutorService pool) {
>         pool.shutdown(); // Disable new tasks from being submitted
>         try {
>             // Wait a while for existing tasks to terminate
>             if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
>                 pool.shutdownNow(); // Cancel currently executing tasks
>                 // Wait a while for tasks to respond to being cancelled
>                 if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
>                     System.err.println("Pool did not terminate");
>                 }
>             }
>         } catch (InterruptedException ie) {
>             // (Re-)Cancel if current thread also interrupted
>             pool.shutdownNow();
>             // Preserve interrupt status
>             Thread.currentThread().interrupt();
>         }
>     }
>
> }
>

Re: Multi threading in a service

Posted by Dmitry Gusev <dm...@gmail.com>.
Hi,

Why don't you want to use ParallelExecutor?
https://tapestry.apache.org/parallel-execution.html

It does exactly this.

If you want to do this yourself you'll need to invoke
PerthreadManager.cleanup() after each iteration to support per thread
services, like JPA's entity manager, etc.


On Wed, Jul 8, 2015 at 8:59 PM, George Christman <gc...@cardaddy.com>
wrote:

> I'm wondering what the best approach would be to handle multi threading in
> a service so that I have other service classes available to me.
>
> I'm passing in PDFService, but I'd like to pass it in through constructor
> injection.
>
> I'm assuming I'd have to instantiate the pool within archiveQueue and not
> set a class variable followed by me binding WorkQueue to an interface? I
>
> Current Code
>
> public class WorkQueue {
>
>     private final ExecutorService pool;
>
>     private final PDFService pdfService;
>
>     public WorkQueue(PDFService pdfService, int poolSize) {
>         this.pdfService = pdfService;
>         this.pool = Executors.newFixedThreadPool(poolSize);
>     }
>
>     public void archiveQueue(List<TimeSheet> timeSheets) {
>         try {
>             for (final TimeSheet timeSheet : timeSheets) {
>                 pool.execute(new Runnable() {
>                     @Override
>                     public void run() {
>                         pdfService.generatePDF(null, timeSheet);
>                     }
>                 });
>             }
>         } catch (Exception ex) {
>             Logger.getLogger(WorkQueue.class.getName()).log(Level.SEVERE,
> null, ex);
>         }
>     }
>
>     void shutdownAndAwaitTermination(ExecutorService pool) {
>         pool.shutdown(); // Disable new tasks from being submitted
>         try {
>             // Wait a while for existing tasks to terminate
>             if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
>                 pool.shutdownNow(); // Cancel currently executing tasks
>                 // Wait a while for tasks to respond to being cancelled
>                 if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
>                     System.err.println("Pool did not terminate");
>                 }
>             }
>         } catch (InterruptedException ie) {
>             // (Re-)Cancel if current thread also interrupted
>             pool.shutdownNow();
>             // Preserve interrupt status
>             Thread.currentThread().interrupt();
>         }
>     }
>
> }
>



-- 
Dmitry Gusev

AnjLab Team
http://anjlab.com