Packing Manager-Worker Threaded Skeleton

From CSclasswiki
Revision as of 17:14, 31 January 2015 by Thiebaut (talk | contribs) (Created page with "--~~~~ ---- <source lang="java"> import java.util.ArrayList; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import processing.core.PA...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

--Thiebaut 17:14, 31 January 2015 (EST)


import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import processing.core.PApplet;

/**
 * SkeletonDemo
 * D. Thiebaut
 * 
		main GUI thread starts 1 thread: manager
		manager starts 2 worker threads.
		each worker thread given N/2 rects (ints in this demonstration case)
		each worker thread packs (N/2 - N') rects (adds ints together) where N' is some number
		and represents rects that did not fit.  
		N' Could be 0.
		when done, worker threads return N' to manager thread
		manager thread gives list of N' rects from worker1 to worker2, and N" rects from worker2 to worker1
		manager thread then stops
		when both worker threads are done with their respective N' rects, they stop
		the GUI thread keeps on going and interacting with user when manager is done
 *
 */

/*
__        __         _             
\ \      / /__  _ __| | _____ _ __ 
 \ \ /\ / / _ \| '__| |/ / _ \ '__|
  \ V  V / (_) | |  |   <  __/ |   
   \_/\_/ \___/|_|  |_|\_\___|_|   
                                   
 */
class WorkerThread extends Thread {
	int Id;
	BlockingQueue<Integer> commandQueue;
	BlockingQueue<Integer> statusQueue;
	ArrayList<Integer>list;
	ArrayList<Integer> leftOverList;
	
	WorkerThread( int id, BlockingQueue cq, BlockingQueue sq, ArrayList<Integer> L ) {
		Id = id;
		commandQueue = cq;
		statusQueue = sq;
		list = L;
		leftOverList = null;
	}
	
	public void run() {
		int sum = 0;
		int forcedLeftOver = Id * 10; // Worker1 will have 10 rects left over, Worker2 20
		
		System.out.println( "Worker " + Id + " started" );

		while ( list.size() > forcedLeftOver ) {
			sum += list.remove( 0 );
		}
		
		System.out.println( "Worker " + Id + " computed first sum = " + sum );
		
		// tell the manager we're done and what we have left over.
		statusQueue.add( Id * 1000000 + forcedLeftOver ); 
		
		// wait till manager gives us a non-null left-over list
		while ( leftOverList == null ) {
			try {
				sleep( 1000 );	 // sleep for 1 ms
			} catch (InterruptedException e) {
			} 
			System.out.println( "Worker " + Id + " sleeping..." );
		}
		
		// process the new list
		while ( ! leftOverList.isEmpty() )
			sum += leftOverList.remove( 0 );
		
		System.out.println( "Thread " + Id + " Done! sum = " + sum );
	}
	
	public ArrayList<Integer> getLeftOver() {
		return list;
	}

	public void setLeftOver(ArrayList<Integer> leftOver ) {
		leftOverList = leftOver;
	}
}
	
/*
 __  __                                   
|  \/  | __ _ _ __   __ _  __ _  ___ _ __ 
| |\/| |/ _` | '_ \ / _` |/ _` |/ _ \ '__|
| |  | | (_| | | | | (_| | (_| |  __/ |   
|_|  |_|\__,_|_| |_|\__,_|\__, |\___|_|   
                          |___/  
 */
class ManagerThread extends Thread {
	ArrayList<Integer> rects;
	BlockingQueue<Integer> commandQueue1, commandQueue2;
	BlockingQueue<Integer> statusQueue;
	WorkerThread worker1, worker2;
	ArrayList<Integer> list1, list2, leftOver1, leftOver2;
	
	ManagerThread() {
		commandQueue1 = new ArrayBlockingQueue<Integer>(20);
		commandQueue2 = new ArrayBlockingQueue<Integer>(20);
		statusQueue   = new ArrayBlockingQueue<Integer>(20);

		list1   = new ArrayList<Integer>();  // simulates the list of rects
		list2   = new ArrayList<Integer>();
		
		worker1 = new WorkerThread( 1, commandQueue1, statusQueue, list1 );
		worker2 = new WorkerThread( 2, commandQueue2, statusQueue, list2 );
	}
	
	public void run() {
		System.out.println( "Manager started" );
		
		// fill the list with stuff for both workers
		for ( int i=0; i<500; i++ ) list1.add( i );
		for ( int i=500; i<1000; i++ ) list2.add( i );
		
		// start both workers
		worker1.start();
		worker2.start();
		
		// wait for two DONE messages from workers.  Worker1 sends 1000000 + N1 where N1
		// is # of leftover rects.  Worker2 sends 2000000 + N2 where N2 is # of leftover
		// rects
		for ( int i=0; i<2; i++ ) {
			try {
				// try to get an int from the statusQueue.  Fall asleep until an int
				// actually shows up in it.
				int N = statusQueue.take();
				if ( N >= 2000000 )
					leftOver2 = worker2.getLeftOver();
				else
					leftOver1 = worker1.getLeftOver();
				System.out.println( "Manager got message " + N + " in statusQueue" );
			} catch (InterruptedException e) {
			}
		}
		
		// swap leftOver lists 
		worker1.setLeftOver( leftOver2 );
		worker2.setLeftOver( leftOver1 );
		
		// wait till 2 workers are done
		try {
			worker1.join();
			worker2.join();
		} catch (InterruptedException e) {
		}

		System.out.println( "Manager done!" );
	}
}

/*
 * 
 ____  _        _      _              ____                       
/ ___|| | _____| | ___| |_ ___  _ __ |  _ \  ___ _ __ ___   ___  
\___ \| |/ / _ \ |/ _ \ __/ _ \| '_ \| | | |/ _ \ '_ ` _ \ / _ \ 
 ___) |   <  __/ |  __/ || (_) | | | | |_| |  __/ | | | | | (_) |
|____/|_|\_\___|_|\___|\__\___/|_| |_|____/ \___|_| |_| |_|\___/ 

Just a Processing application that starts the manager thread, and
then interacts with the user via a simple GUI allowing user to draw
with mouse.
*/
public class SkeletonDemo extends PApplet {
	float lastX, lastY;
	ManagerThread manager;
	
	public void setup() {
		size( 400, 200 );
		smooth();
		manager = new ManagerThread();
		manager.start();
	}
	
	public void draw() {
		//background( 255 );
		if ( lastX != 0 )
			line( mouseX, mouseY, lastX, lastY );
		lastX = mouseX;
		lastY = mouseY;
	}
	
}