multithreading - Java thread program not working using wait() and notifyAll() -
below program. thread 0 gets printer, other threads not it. there 1 printer object, , want multiple job threads use printer. how make program work jobs printer. me code flow seems fine. synchronizing on single printer object. please help.
package classestesting; public class printerqueue { final static printer printer = new printer();; public static void main(string[] args) { // todo auto-generated method stub system.out.println("in main"); (int = 0; < 5; i++) { new thread(new jobs(), "thread - " + i).start(); system.out.println("started " + + " thread"); } } } class printer { private boolean isused; printer() { this.isused = false; } public void setused(boolean used) { this.isused = used; } public boolean isused() { return this.isused; } } class jobs implements runnable { string name; boolean isdataavailble; jobs() { this.isdataavailble = true; } public void setnodata(boolean nodata) { this.isdataavailble = false; } @override public void run() { while (isdataavailble) { if (printerqueue.printer.isused()) { try { system.out.println(thread.currentthread() + "waiting printer"); synchronized (printerqueue.printer) { printerqueue.printer.wait(); } } catch (interruptedexception e) { e.printstacktrace(); } } else { synchronized (printerqueue.printer) { system.out.println(thread.currentthread() + "got printer"); printerqueue.printer.setused(true); try { thread.sleep(3000); } catch (interruptedexception e) { e.printstacktrace(); } printerqueue.printer.setused(false); printerqueue.printer.notify(); } } } try { thread.sleep(3000); } catch (interruptedexception e) { e.printstacktrace(); } } }
hi, have revised program getting lock first condition checking. thread 0 gets printer. other threads starve.
revised program:
package classestesting; public class printerqueue { static printer printer; public static void main(string[] args) { // todo auto-generated method stub system.out.println("in main"); printer = new printer(); (int = 0; < 5; i++) { jobs j1 = new jobs(); j1.setprinter(printer); thread t1 = new thread(j1, "thread - " + i); t1.start(); system.out.println("started " + + " thread"); } } } class printer { private boolean isused; printer() { this.isused = false; } public void setused(boolean used) { this.isused = used; } public boolean isused() { return this.isused; } } class jobs implements runnable { string name; printer printer; public printer getprinter() { return printer; } public void setprinter(printer printer) { this.printer = printer; } boolean isdataavailble; jobs() { this.isdataavailble = true; } public void setnodata(boolean nodata) { this.isdataavailble = false; } @override public void run() { while (isdataavailble) { synchronized (printerqueue.printer) { if (this.printer.isused()) { try { system.out.println(thread.currentthread() + "waiting printer"); printerqueue.printer.wait(); } catch (interruptedexception e) { e.printstacktrace(); } } else { system.out.println(thread.currentthread() + "got printer"); printerqueue.printer.setused(true); try { thread.sleep(3000); } catch (interruptedexception e) { e.printstacktrace(); } printerqueue.printer.setused(false); printerqueue.printer.notify(); } } } } }
if want resource available threads in fair manner, it's better use reentrantlock
fair = true
parameter. never rely on non-volatile variables changed in concurrent way. here's fixed code:
import java.util.concurrent.locks.lock; import java.util.concurrent.locks.reentrantlock; public class printerqueue { static printer printer; public static void main(string[] args) { system.out.println("in main"); printer = new printer(); (int = 0; < 5; i++) { // added printer constructor parameter pass same printer // jobs new thread(new jobs(printer), "thread - " + i).start(); system.out.println("started " + + " thread"); } } } class printer { // internally printer holds fair reentrantlock lock lock = new reentrantlock(true); // call printer public void acquire() { lock.lock(); } // call release printer, it's available other threads public void release() { lock.unlock(); } } class jobs implements runnable { // declare isdataavailble volatile you're going change thread volatile boolean isdataavailble; private final printer printer; // constructor takes printer argument jobs(printer printer) { this.isdataavailble = true; this.printer = printer; } @override public void run() { try { while (isdataavailble) { system.out.println(thread.currentthread() + "trying printer"); // printer this.printer.acquire(); try { system.out.println(thread.currentthread() + "printer acquired!"); // use thread.sleep(3000); } { // release printer. better in block // release if unexpected exception occurs this.printer.release(); } } thread.sleep(3000); } catch (interruptedexception e) { e.printstacktrace(); } } }
Comments
Post a Comment