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場合は呼び出さないでください。どうすればこれを保証できますか? 簡単な方法は、すべてを?でラップすることです。しかし、それは、一度に印刷しようとしているクライアントが1つだけで、呼び出されないことを意味しますか? どうすればこの問題を解決できますか?printer.isAvailable() == falseprinter.isFair(client) == falsesynchronized (printer)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 に答える