Help with Java Multithreading -
alright, sort of dual-purpose question. main thing hope take away more knowledge of multithreading. complete newbie when comes multithreading, , first actual attempt in multiple threads. other thing hope take away piece of homework turning more complicated franken-project fun , learning. in first part of question going detail thinking , methodology threads have been working on in homework assignment. if doing bad practice, needs fixed, whatever, please let me know can learn. again, know practically nothing multithreading.
first off, taking computer science course which, nice it, has homework uses techniques , data structures i've learned , not challenging. attempt not entirely bored out of skull, trying take simple project (creating linked list , sorted linked list) , turn multi-threaded franken-program. method adding new elements in separate thread , gets input queue (not entirely necessary un-ordered list, more useful proper ordering), , ordered list want separate thread patrol list make sure elements in order (one of methods not allowed change returns references entire nodes, have public data). 2 main things want create, not things might want try , figure out. meant pretty test learn multithreading, i'm not particularly designing project practicality. if want leave comment programming practice should threaded or not, highly appreciated.
as step took recently, idea gleaned reading post on stackoverflow itself, have created master class has threads passed can stop them , clean @ end of program. done through use somethread.interrupt() , having thread's run() method checking exception. however, have found problem method: loop runs through threads , calling interrupt(), times, not run. here code method:
public static void stopallthreads() { boolean stopped = false; while( !stopped ) { system.out.println( "stopping threads" ); synchronized( threads ) { system.out.println( "threads being stopped: " + threads.size() ); for( int = 0; < threads.size(); i++ ) { system.out.println( "stopping: " + threads.get( ) ); threads.get( ).interrupt(); } threads.clear(); stopped = true; } } }
while attempting debug it, put in while loop try , force method run loop, happens outputs "stopping threads" , never see else. don't know if bad way code, or wrong code. figuring out how make work appreciated (if need see more of class, please let me know. don't know need see, don't want copy , paste several entire java files).
on top of problem, have determined when running program, reach last line , attempt stop threads before thread going through queue of numbers add list finished adding everything. problem when attempting output list through tostring method directly after adding numbers queue, nothing yet added, , nothing output console. here main method shows order of things happening (though imagine less important when dealing threading):
public static void main( string[] args ) { // make sure first thing created activethreads bla = new activethreads(); comparator< integer > temp = new comparator< integer >() { public int compare( integer i, integer j ) { if( > j ) return 1; if( < j ) return -1; return 0; } }; list< integer > woogle = new list< integer >( temp ); woogle.add( 1 ); woogle.add( 2 ); woogle.add( 3 ); woogle.add( 4 ); system.out.println( woogle ); activethreads.stopallthreads(); }
lastly, here custom thread have made supposed check queue elements, add elements in queue actual list:
private class addthread implements runnable { public addthread() { } public void run() { while( running ) { synchronized( addqueue ) { while( !addqueue.isempty() ) { system.out.println( "going through queue" ); t temp = addqueue.poll(); if( head == null ) { head = new node< t >(); last = head; head.data = temp; largest = temp; smallest = temp; } else { last.next = new node< t >(); last.next.data = temp; last = last.next; if( mcomparator.compare( temp, largest ) == 1 ) { largest = temp; } else if( mcomparator.compare( temp, smallest ) == -1 ) { smallest = temp; } } ++size; } } system.out.println( "pausing " + addthread ); synchronized( addthread ) { pause( 200 ); } } } private void pause( long time ) { try { addthread.wait( time ); } catch ( interruptedexception e ) { running = false; addthread.notify(); } } private boolean running = true; }
now, absolute last thing ask of basic primers , guidelines , such multithreading. have found amount of tutorials, there things people don't mention in tutorials, tutorials so-so. if know of tutorials, appreciate links them. if there coding methodologies multithreading, appreciated well. sort of information think might me wrap brain around concept, make sure when implementing it, in way less prone bugs , people won't yell @ me bad practices.
edit: answer questions matt b put comment, addthread purely reference thread looks @ queue has elements in add list , puts them list. private thread inside of class containing addthread class (clever use of names, eh?). threads constructed in way posted in question @ stackoverflow. here example (and snippet of code showing addthread is):
addthread = new thread( new addthread(), "thread adding elements" ); addthread.setpriority( 6 ); addthread.start(); activethreads.addthread( addthread );
all threads created in similar way. thread posted supposed doing, did explain in detail above, i'll try put synopsis here.
the addthread class inner class gets created @ time of construction of linked list class trying make. looks @ private queue may or may not have elements in it, , when does, puts elements linked list. queue gets added when linked list's add( t newelt ) method called.
edit edit: in interest of full disclosure, , wish take time, going post entirety of 2 relevant java files here.
list.java
public class list< t > implements iterable< t >, comparable< list< t > > { // may not change inner class! class node< d > { d data; node< d > next; } public list( comparator< t > comparator ) { mcomparator = comparator; head = null; last = null; size = 0; addqueue = new linkedlist< t >(); addthread = new thread( new addthread(), "thread adding elements" ); addthread.setpriority( 6 ); addthread.start(); activethreads.addthread( addthread ); } public void add( t newelt ) { synchronized( addqueue ) { addqueue.add( newelt ); } } public t get( int index ) { if( index > size ) throw new indexoutofboundsexception(); node< t > temp = head; for( int = 0; < index; i++ ) { temp = temp.next; } return temp.data; } public node< t > lookup( t element ) { node< t > temp = head; for( int = 0; < size; i++ ) { if( temp.data == element ) return temp; temp = temp.next; } throw new nosuchelementexception(); } public int size() { return size; } public boolean isempty() { return head == null; } public void delete( t element ) { throw new unsupportedoperationexception("you must implement method."); } public void replace( t oldelt, t newelt ) { try { node< t > temp = lookup( oldelt ); temp.data = newelt; } catch( nosuchelementexception e ) { throw e; } } public t getlargest() { return largest; } public t getsmallest() { return smallest; } public list< t > copy() { throw new unsupportedoperationexception("you must implement method."); } public string tostring() { stringbuffer ret = new stringbuffer(); int = 0; for( t x : ) { system.out.println( "loop: " + i++ ); ret.append( x + " " ); } return ret.tostring(); } public int compareto( list< t > other ) { throw new unsupportedoperationexception("you must implement method."); } public listiterator< t > iterator() { return new listiterator< t >( head ); } private class listiterator< e > implements iterator< e > { private listiterator( node< e > head ) { cur = head; } public boolean hasnext() { if( cur == null ) return false; system.out.println( "iterator: " + cur.data ); return cur.next == null; } @suppresswarnings("unchecked") public e next() { node< e > temp = cur; cur = cur.next; return (e)temp.data; } public void remove() { throw new unsupportedoperationexception("you not need implement " + "this method."); } private node< e > cur; } private class addthread implements runnable { public addthread() { } public void run() { while( running ) { synchronized( addqueue ) { while( !addqueue.isempty() ) { system.out.println( "going through queue" ); t temp = addqueue.poll(); if( head == null ) { head = new node< t >(); last = head; head.data = temp; largest = temp; smallest = temp; } else { last.next = new node< t >(); last.next.data = temp; last = last.next; if( mcomparator.compare( temp, largest ) == 1 ) { largest = temp; } else if( mcomparator.compare( temp, smallest ) == -1 ) { smallest = temp; } } ++size; } } system.out.println( "pausing " + addthread ); synchronized( addthread ) { pause( 200 ); } } } private void pause( long time ) { try { addthread.wait( time ); } catch ( interruptedexception e ) { running = false; addthread.notify(); } } private volatile boolean running = true; } private comparator< t > mcomparator; private node< t > head, last; private thread addthread; // replace own created class later private queue< t > addqueue; private int size; private t largest, smallest; }
activethreads.java
public class activethreads { public activethreads() { if( threads == null ) { threads = new arraylist< thread >(); } if( threadsmonitor == null ) { threadsmonitor monitor = new threadsmonitor(); thread thread = new thread( monitor, "active threads monitor" ); thread.setpriority( 3 ); thread.start(); threadsmonitor = thread; } } public static void stopmonitoring() { synchronized( threadsmonitor ) { threadsmonitor.interrupt(); } } public static void addthread( thread t ) { synchronized( threads ) { threads.add( t ); system.out.println( "added thread: " + t ); } } public static void addthread( runnable r, string s ) { thread t = new thread( r, s ); t.start(); addthread( t ); } public static void stopthread( thread t ) { synchronized( threads ) { for( int = 0; < threads.size(); i++ ) { if( threads.get( ) == t ) { threads.get( ).interrupt(); threads.remove( ); } } } } public static void stopallthreads() { boolean stopped = false; while( stopped == false ) { system.out.println( "stopping threads" ); synchronized( threads ) { system.out.println( "threads being stopped: " + threads.size() ); for( int = 0; < threads.size(); i++ ) { system.out.println( "stopping: " + threads.get( ) ); threads.get( ).interrupt(); } threads.clear(); stopped = true; } } } private static arraylist< thread > threads = null; private static thread threadsmonitor = null; private class threadsmonitor implements runnable { public threadsmonitor() { } public void run() { while( true ) { synchronized( threads ) { for( int = 0; < threads.size(); i++ ) { if( !threads.get( ).isalive() ) { threads.get( ).interrupt(); threads.remove( ); } synchronized( threadsmonitor ) { try { threadsmonitor.wait( 5000 ); } catch( interruptedexception e ) { threadsmonitor.interrupted(); return; } } } } } } } }
it's hard see whole picture general points , more general suggestions.
while attempting debug it, put in while loop try , force method run loop, happens outputs "stopping threads" , never see else
this because thread sitting in sychronized block using same lock , preventing code running. easiest way find out run in debugger , pause/break program when think may stuck. should able inspect threads , check state. blocked status.
the while( !stopped )
in stopallthreads
redundant because can never loop.
in addthread
have this
private boolean running = true;
when using boolean stop flag (which think trying achieve) , stop flag polled 1 thread set must make volatile
. there whole area of java multithreading coding deals data visibility , volatile
1 of tools used ensure correctness.
often programs work "fine of time" without "correct" multithreading logic. broken , break @ inconvenient time (usually customer gets hold of it)! (if remember 1 thing in answer remember previous sentence :d )
leverage java.util.concurrent
package as can. although important understand fundamentals too, package has lots of useful constructs designed clever people solve many common concurrency problems.
read java concurrent in practice. topic describing (potentially dry) explains concepts in accessible way plenty of examples. written same group worked on java.util.concurrent
package.
from own experience think "visibility" of data in concurrent programs important , least understood part of java thread programming. if can head round on way. jcip can this.
hope above helps , luck!
edit: spotted problem in additional code construct
for( int = 0; < threads.size(); i++ ) { if( !threads.get( ).isalive() ) { threads.get( ).interrupt(); threads.remove( ); } }
doing remove() inside indexed scan of list not work expected because remove() interferes indexes of other items in list (all subsequent items shifted down 1 index).
Comments
Post a Comment