All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codeartisans.java.sos.threading.DefaultWorkQueue Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2009, Paul Merlin. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.codeartisans.java.sos.threading;

import com.google.inject.Inject;
import com.google.inject.name.Named;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.LinkedList;

import org.codeartisans.java.toolbox.async.ErrorCallbackAdapter;
import org.codeartisans.java.toolbox.exceptions.NullArgumentException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Paul Merlin
 * @author Fabien Barbero
 */
public final class DefaultWorkQueue
        implements WorkQueue
{

    private static final Logger LOGGER = LoggerFactory.getLogger( DefaultWorkQueue.class );
    // CHECKSTYLE:OFF We use a specific List implementation on purpose
    private final LinkedList queue;
    // CHECKSTYLE:ON

    @Inject
    @SuppressWarnings( "CallToThreadStartDuringObjectConstruction" )
    public DefaultWorkQueue( @Named( NAME ) String name, @Named( SIZE ) Integer size )
    {
        NullArgumentException.ensureNotEmpty( NAME, true, name );
        NullArgumentException.ensureNotZero( SIZE, size );
        queue = new LinkedList();
        PooledWorker[] threads = new PooledWorker[ size ];
        ThreadGroup threadGroup = new ThreadGroup( name + "WorkQueue" );
        for ( int i = 0; i < size; i++ ) {
            threads[i] = new PooledWorker( threadGroup, name + "Worker-" + i );
            threads[i].start();
        }
    }

    @Override
    public void enqueue( Runnable r )
    {
        enqueue( r, null );
    }

    @Override
    public void enqueue( Runnable runnable, ErrorCallbackAdapter errorCallback )
    {
        synchronized ( queue ) {
            queue.addLast( new RunnableCallbackHolder( runnable, errorCallback ) );
            queue.notifyAll();
        }
    }

    private class PooledWorker
            extends Thread
    {

        private PooledWorker( ThreadGroup threadGroup, String threadName )
        {
            super( threadGroup, threadName );
        }

        @Override
        public void run()
        {
            RunnableCallbackHolder holder;
            while ( true ) {
                synchronized ( queue ) {
                    while ( queue.isEmpty() ) {
                        try {
                            queue.wait();
                        } catch ( InterruptedException ignored ) {
                        }
                    }
                    holder = queue.removeFirst();
                }
                // If we don't catch RuntimeException, the pool could leak threads
                try {
                    holder.runnable().run();
                } catch ( RuntimeException ex ) {
                    if ( holder.errorCallback() != null ) {
                        holder.errorCallback().onError( ex.getMessage(), ex );
                    } else {
                        notifyUncaughtException( ex );
                    }
                }
            }
        }

        private void notifyUncaughtException( Throwable e )
        {
            UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
            if ( handler != null ) {
                handler.uncaughtException( this, e );
            } else {
                LOGGER.error( "Uncaught exception in queued work - " + e.getMessage(), e );
            }
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy