1

我遇到的问题是:在打印服务器的多线程模拟中,我需要做一些类似的事情:

// in client
if (printer.isAvailable() && printer.isFair(this)) // is fair checks if its fair to allow client to print now
    printer.requestToPrint(something)
else
    printer.requestToPrintNext() // something like go into queue 

问题是:requestToPrint不应该被调用 ifprinter.isAvailable() == false或者printer.isFair(client) == false(甚至在函数内)。我怎样才能确保这一点?简单的方法可能是将所有内容都包装在synchronized (printer)? 但这意味着我将只有 1 个客户在任何时候尝试打印,requestToPrintNext永远不会被调用?我该如何解决这个问题?

顺便说一句,所有这些功能都在Interface提供中定义,因此我认为我需要使用所有这些功能......

4

2 回答 2

2

通常处理打印机的方法是将打印作业组织成一个队列,具有单一接口功能,如果打印机空闲则立即开始打印,否则将作业放入队列中。如果提供的接口有这样的功能,请使用它。如果没有,请创建自己的。如果打印是同步的,即在打印完所有内容之前不返回,则从单独的线程中调用它。

于 2013-03-16T03:34:07.340 回答
1

乍一看,您的客户似乎有太多的打印机逻辑。我认为客户的方法更像:

public void printMe() {
    printer.print(this);
}

打印机将处理所有可用的检查、排队和调度:

public synchronized boolean print(Client c, Something something) {
    if(isFair(c) && isAvailable()) {
        requestToPrint(something);
    }
    else {
        // queue
        // Not sure what "requestToPrintNext" does, 
        // as it has no argument, like "something"
    }
}

同步的打印方法将防止其他客户端相互跳过(下一个客户端将被阻止,直到当前客户端的方法完成)。正如其他海报所提到的,如果该requestToPrint方法需要很长时间,您可以将其线程化(只需确保它首先以某种方式将 isAvailable 设置为 false,以便下一个客户端将正确排队)。

上述print方法假设该requestToPrint方法只是简单地触发一个打印作业,并且不会阻塞整个打印操作。示例实现可能类似于:

public void requestToPrint(Client c) {

    setAvailable(false);

    Thread job = new Thread(new Runnable() {
        @Override
        public void run() {

            // The actual print work

            setAvailable(true);
        }
    });

    job.start();
}

可能值得注意的是,此实现非常特定于该问题的约束。对于更通用的方法,具有单个工作线程来服务该队列的单个打印队列(如其他答案所引用)总体上会更干净。一个非常简单的骨架是:

public void print(Client c) {
    synchronized(queue) {
        queue.add(c);
    }
}

public class PrintWorker implements Runnable {
    @Override
    public void run() {
        while(true) {
            Client c = null;
            synchronized(queue) {
                if(!queue.isEmpty()) {
                    c = queue.remove(0);
                }
            }

            if(c != null) {
                // do print work
            }
            else {
                // maybe add sleep or wait here
                // to keep thread from spinning
                // too fast and burning CPU
            }
        }
    }
} 
于 2013-03-16T06:04:52.863 回答