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

com.meliorbis.numerics.threading.MultiThreadedExecutor Maven / Gradle / Ivy

Go to download

A library for working with large multi-dimensional arrays and the functions they represent

There is a newer version: 1.2
Show newest version
/**
 *
 */
package com.meliorbis.numerics.threading;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.logging.Logger;

import com.meliorbis.numerics.NumericsException;

/**
 * Executes callables on a configured ExecutorService
 *
 * @author toby
 */
public class MultiThreadedExecutor implements Executor
{
    private static final int DEFAULT_THREAD_COUNT = 0;
    private final int _threadCount;
    private final ForkJoinPool _pool;
	private CurrentThreadExecutor _currentThreadExec;
	
    public MultiThreadedExecutor()
    {
        this(DEFAULT_THREAD_COUNT);
    }

    public MultiThreadedExecutor(int threadCount_)
    {
        _currentThreadExec = new CurrentThreadExecutor();
        
        if(threadCount_ == 0)
        {
            _pool = ForkJoinPool.commonPool();
        }
        else
        {
            _pool = new ForkJoinPool(threadCount_);
        }

       Logger.getAnonymousLogger().info("Parallelism: "+_pool.getParallelism());
       _threadCount = _pool.getParallelism();
    }

    public MultiThreadedExecutor clone()
    {
        return new MultiThreadedExecutor(_threadCount);
    }
    
    private class BatchAction implements Callable
    {
    	List _actions;
    	int _from;
    	int _to;
    	
    	
		public BatchAction(List actions_, int from_, int to_)
		{
			super();
			_actions = actions_;
			_from = from_;
			_to = to_;
		}


		@Override
		public Object call() throws Exception
		{
			_currentThreadExec.executeAndWait(_actions.subList(_from, _to));
			
			return null;
		}
    }

    /* (non-Javadoc)
     * @see com.meliorbis.numerics.threading.IExecutor#executeAndWait(java.util.Collection)
     */
    @Override
    public void executeAndWait(List actions_)
    {
        /* Put the actions in the pool for execution
         */
        //actions_.forEach(_pool::execute);
    	try
		{
	    	if(actions_.size() > _threadCount) {
	    		
	    		int first = 0;
	    		List batches = new ArrayList(_threadCount+1);
	    		
	    		int batchSize = actions_.size()/_threadCount;
	    		
	    		while(first < actions_.size())
	    		{
	    			int end = Math.min(actions_.size(), first+batchSize);
	    			batches.add(new BatchAction(actions_,first, end));
	    			first = end;
	    		}
	    		
	    		List> invokeAll = _pool.invokeAll(batches);
	    		
	    		for (Future future : invokeAll)
				{
					future.get();
				}
	    	}
	    	else
			{
	    		List> results = _pool.invokeAll(actions_);
	    		
				for (Future future : results)
				{
					future.get();
				}
			}
		} catch (InterruptedException e)
		{
			throw new NumericsException(e);
		}
    	catch (ExecutionException e)
		{
    		throw new NumericsException(e);
		}
//        final ListIterator reverseIterator = actions_.listIterator(actions_.size());
//
//        /*  Wait for them all to finish, in reverse order (faster according to Java Doc
//         */
//        while (reverseIterator.hasPrevious())
//        {
//            reverseIterator.previous().join();
//        }
        
    }

    private class BatchTask implements Callable>
    {
    	List> _actions;
    	int _from;
    	int _to;
    	
    	
		public BatchTask(List> actions_, int from_, int to_)
		{
			_actions = actions_;
			_from = from_;
			_to = to_;
		}


		@Override
		public List call() throws Exception
		{
			return _currentThreadExec.executeAndGet(_actions.subList(_from, _to));
		}
    }
    
    /* (non-Javadoc)
     * @see com.meliorbis.numerics.threading.IExecutor#executeAndWait(java.util.Collection)
	 */
    @Override
    public  List executeAndGet(List> tasks_) throws NumericsException
    {
        /* Put the actions in the pool for execution
         */
        //tasks_.forEach(_pool::execute);
       List results = new ArrayList(tasks_.size());

        try
		{
        	if(tasks_.size() > _threadCount) {
	    		
	    		int first = 0;
	    		List> batches = new ArrayList>(_threadCount+1);
	    		
	    		int batchSize = tasks_.size()/_threadCount;
	    		
	    		while(first < tasks_.size())
	    		{
	    			int end = Math.min(tasks_.size(), first+batchSize);
	    			batches.add(new BatchTask(tasks_,first, end));
	    			first = end;
	    		}
	    		
	    		List>> batchResults = _pool.invokeAll(batches);

	    		for (Future> future : batchResults)
				{
					results.addAll(future.get());
				}
	    	}
        	else
        	{
        		List> futures = _pool.invokeAll(tasks_);
			
				for (Future future : futures)
				{
					results.add(future.get());
				}
        	}
			
		} catch (InterruptedException e)
		{
			throw new NumericsException(e);
		} catch (ExecutionException e)
		{
			throw new NumericsException(e);
		}

//        final ListIterator reverseIterator = tasks_.listIterator(tasks_.size());
//
//        int currentIndex = tasks_.size()-1;
//
//        /*  Wait for them all to finish, in reverse order (faster according to Java Doc
//         */
//        while (reverseIterator.hasPrevious())
//        {
//            results[currentIndex--] = reverseIterator.previous().join();
//        }

        return results;

    }

    @Override
    public void destroy()
    {
    	_pool.shutdown();
    }

}