[英]Java thread program not working using wait() and notifyAll()
以下是我的计划。 始终线程0获取打印机,其他线程不获取它。 有一个打印机对象,我想要多个作业线程来使用打印机。 如何使该程序工作,以便所有作业都能获得打印机。 对我来说,代码流似乎很好。 我正在同一个打印机对象上同步。 请帮忙。
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");
for (int i = 0; i < 5; i++) {
new Thread(new Jobs(), "Thread - " + i).start();
System.out.println("started " + i + " 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 FOR 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();
}
}
}
嗨,我已经修改了我的程序,先获取锁定然后进行条件检查。 即使这样,线程0总是得到打印机。 其他线程饿死。
修订计划:
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();
for (int i = 0; i < 5; i++) {
Jobs j1 = new Jobs();
j1.setPrinter(printer);
Thread t1 = new Thread(j1, "Thread - " + i);
t1.start();
System.out.println("started " + i + " 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 FOR 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();
}
}
}
}
}
我认为你所寻找的是Condition
。 您首先需要获得一个锁,然后您可以检查一个条件。 虽然那个条件持有线程会睡觉。 当条件不再保持时,睡眠线程(或下一个睡眠线程)被唤醒以再次检查该条件。
您可以在此处阅读有关Condition
对象的更多信息: http : //docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html
如果您希望资源以公平的方式可用于所有线程,那么使用带有fair = true
参数的ReentrantLock
会更好。 也永远不要依赖于并发方式改变的非易失性变量。 这是固定代码:
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();
for (int i = 0; i < 5; i++) {
// I added printer constructor parameter to pass the same printer
// to all the Jobs
new Thread(new Jobs(printer), "Thread - " + i).start();
System.out.println("started " + i + " thread");
}
}
}
class Printer {
// internally printer holds a fair ReentrantLock
Lock lock = new ReentrantLock(true);
// call this to get the printer
public void acquire() {
lock.lock();
}
// call this to release the printer, so it's available for other threads
public void release() {
lock.unlock();
}
}
class Jobs implements Runnable {
// Declare isDataAvailble as volatile as you're going to change it from another thread
volatile boolean isDataAvailble;
private final Printer printer;
// constructor now takes the printer argument
Jobs(Printer printer) {
this.isDataAvailble = true;
this.printer = printer;
}
@Override
public void run() {
try {
while (isDataAvailble) {
System.out.println(Thread.currentThread()
+ "Trying to get the printer");
// get the printer
this.printer.acquire();
try {
System.out.println(Thread.currentThread()
+ "Printer acquired!");
// use it
Thread.sleep(3000);
} finally {
// Release the printer. Better to do it in finally block
// so you will release it even if some unexpected exception occurs
this.printer.release();
}
}
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
它应该如下所示:
购买打印机:
synchronized (PrinterQueue.printer) { while (PrinterQueue.printer.isUsed()) { try { System.out.println(Thread.currentThread() + "WAITING FOR PRINTER"); PrinterQueue.printer.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread() + "GOT PRINTER"); PrinterQueue.printer.setUsed(true); }
使用打印机,按照您的代码通过Thread.sleep()
进行Thread.sleep()
:
try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
释放打印机:
synchronized (PrinterQueue.printer) { PrinterQueue.printer.setUsed(false); PrinterQueue.printer.notifyAll(); }
您需要使用while
而不是if
,并且需要测试同步的同一对象。 并使用notifyAll()
而不是notify().
但我不清楚你需要这些,只是一个synchronized
块。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.