最初の宿題
デザインのアイデアと考え
最初の仕事にはピギーバックエレベーターが必要でした。最初の仕事には長い時間がかかり、アーキテクチャについて考えるのに長い時間がかかりました。最初は、入力スレッド、スケジューリングの3つのスレッドに取り組みたかったのです。マシンスレッドとエレベータースレッドは、生産と消費のモデルのチェーンに関与したいが、スケジューラスレッドとエレベータースレッドが相互作用するときにいくつかの問題があります。
- runメソッドの操作を最小限にすることを考え、
- これは、入力スレッドとスケジューラスレッドで比較的簡単です。エレベータースレッドでは、次のような最小化されていない操作を追加するかどうかを検討しました。エレベーターはmoveTo()メソッドを追加します。
- このメソッドはwhile(true)には適していません。サイクルごとに1階を移動できます。
- このmoveToでは、階段を上るのに0.4秒かかるため、時間がかかるという問題があります。この時間中にリクエストに応答するために次のサイクルを実行する方法はありません。
- したがって、runメソッドにはwhile(true)が含まれていますが、小さいものから大きいものまで、毎回最小限のことを行うことをお勧めします
- 3つのスレッドについて考える:入力、スケジューラ、エレベータースレッド
- 最初は3つのスレッドを実装したかったのですが、まだ運用に問題がありましたが、パイプラインは構築されていましたが、エレベーターのスレッドは上下するまでの待ち時間があり、スケジューリングには非常に重要です難しいのは、今回は達成するためにエレベーターの戻りを追加する必要があることですが、そうしませんでした。
- エレベータースレッドを直接スケジューラスレッドに結合しました。現時点では、エレベーター内に時間がない(true)です。エレベーターが終了するまで待ってから、実行を続けます。
- 仕事を渡してみると、この時のエレベーターの糸を糸にする必要がなくなったので、まったく普通の物なので、次の仕事で3本の糸を2本の糸に変えてみました
- このジョブはalsアルゴリズムを使用しており、パフォーマンスがあまり良くないか、外観のパフォーマンスが優れています。
クラス図分析
- クラス間の呼び出しの複雑さは比較的高く、まだ改善の余地があります
メトリック分析
方法 | ev(G) | iv(G) | v(G) |
---|---|---|---|
「Command.Command(boolean)」 | 1 | 1 | 1 |
「Command.addCommand(int)」 | 1 | 3 | 3 |
「Command.getCommand()」 | 1 | 3 | 3 |
「Dispatcher.Dispatcher(LinkedList
|
1 | 1 | 1 |
「Dispatcher.checkIfSomeBodyGetIn()」 | 3 | 2 | 3 |
「Dispatcher.checkIfSomeBodyGetOff()」 | 3 | 2 | 3 |
「Dispatcher.closeDoor()」 | 1 | 2 | 2 |
「Dispatcher.downFloor()」 | 1 | 2 | 2 |
「Dispatcher.getIn()」 | 3 | 4 | 4 |
「Dispatcher.getOff()」 | 3 | 3 | 3 |
「Dispatcher.isSameDir(PersonRequest)」 | 3 | 4 | 5 |
「Dispatcher.openDoor()」 | 1 | 2 | 2 |
「Dispatcher.run()」 | $ \ color {red} {6} $ | $ \ color {red} {13} $ | $ \ color {red} {15} $ |
「Dispatcher.setStop(boolean)」 | 1 | 1 | 1 |
「Dispatcher.upFloor()」 | 1 | 2 | 2 |
「Elevator.Elevator(LinkedList
|
1 | 1 | 1 |
「Elevator.arrive()」 | 1 | 1 | 1 |
「Elevator.close()」 | 1 | 1 | 1 |
「Elevator.down()」 | 1 | 2 | 2 |
「Elevator.getFloorNumNow()」 | 1 | 1 | 1 |
「Elevator.getIrq()」 | 1 | 1 | 1 |
「Elevator.isRuning()」 | 1 | 1 | 1 |
「Elevator.open()」 | 1 | 2 | 2 |
「Elevator.run()」 | 1 | 5 | 5 |
「Elevator.setRuning(boolean)」 | 1 | 1 | 1 |
「Elevator.up()」 | 1 | 2 | 2 |
runメソッドはエレベーターメソッドを複数回呼び出し、新しいスレッドを複数回起動することで複雑さが増す可能性があります。
タイミング図
第二の仕事
デザインのアイデアと考え
このジョブは複数のエレベーター間の共同作業であり、容量の問題が設計されています。最後のジョブを最適化し、最後のジョブのスケジューラとエレベータースレッドを1つのエレベータースレッドにマージしました。 、複数のエレベーター、目標を達成するために使用できるエレベータークラスは1つだけです。同時に、エレベーターの内部スケジューリング戦略はLOOKに変更されます。エレベーターのスケジューリング戦略は、各エレベーターの関数を定義することです:f(a、b、c 、d、e、f);
- aはエレベーターが配置されている階を示します
- bはエレベーターが上昇しているか下降しているかを示します
- cは、リクエストが配置されているフロアを示します
- dは、リクエストが送信されるフロアを示します
- eはエレベーターの外で待っている人の数を表します
- fはエレベーターの人数を表します
- この関数は、エレベーターの負荷を測定するための値を返します
メインスレッドが要求を読み取った後、それは実行するf(a、b、c、d、e、f)の最小値を持つエレベーターに直接割り当てられます。前回からの変更が少ないため、スレッドの安全性の問題はありませんまた、そのようなスケジューリング戦略は、パフォーマンスがより優れた動的スケジューリングスキームでもあります。
クラス図
クラスダイアグラムも比較的単純で、2つのクラスしかありません。エレベータークラスは、最後のジョブのピギーバック関数を組み合わせており、メインメソッドはエレベーター間の分散問題を追加します。
メトリック分析
このジョブの最大値はgetfd()メソッドです。これは、上記のスケジューリング用に定義されたf(a、b、c、d、e、f)ですが、実装にはまだプロセス指向のアイデアがある可能性があります、この方法のサイクルは非常に複雑になります。
タイミング図
第三の宿題
デザインのアイデアと考え
- この操作は、複数のタイプの複数のエレベーター間のスケジューリングです。
- エレベーターは基本的には変更されていませんが、いくつかの構成内容のみが追加されています。ここでは、タイプと判断が直接使用されるかどうかが示されています。
- 前回はクラスが少なすぎるため、一部のクラスでは内部処理が多すぎる可能性があるため、2つのスケジューラクラスが抽象化されましたが、今回はスレッドではなく、マネージャのみです。同じタイプのエレベーター間のスケジューリングスキームは2番目のジョブと同じで、Dispacherクラスが抽象化されます。さまざまなクラスが最初に直接リクエストに分割され、次にエレベーターに割り当てられるため、DispacherTopクラスがあります。上から次の管理に進む
- 今回はハッキングされたスレッドセーフティの問題がありましたが、共有オブジェクトのデザインを削減しようとしていたため、結局、問題がどこにあるのかわかりませんでした。そのため、エレベーターを追加するときの管理レベルに問題がある可能性があります。
クラス図
- クロスレイヤースケジューリングが行われていることがわかります。これは、リクエストが分割された後、エレベーターのキューに入る必要があるためです。次に、2つの分割されたリクエスト、最初のリクエストが完了したら、トップレベルのスケジューラに実行を継続するように指示する必要があります。 。
メトリック分析
- 結合を減らすためにリクエストキューと待機キューを抽象化しなかったため、クラスの複雑さは比較的高くなっています。実際、待機キューは、レイヤー間のスケジューリングを回避するために抽象化できますが、すべて待機キューが付属しています相互作用してデカップリングを実現します。
タイミング図
SOLID設計原理の分析
- 単一の責任の原則:単一の責任の原則:クラスを変更する理由は1つだけにすべきです
- この割り当てでは、単一の責任の原則を達成しようとしますが、場合によっては、クラスに分割するのがより複雑になるため、結合することを選択しました。
- オープンクローズの原則:オープンおよびクローズの原則:クラス、モジュール、関数などのソフトウェアエンティティは、拡張に対してオープンで、変更に対してクローズでなければなりません。
- クラス図の構造が各ジョブで再設計されたため、クラスが変更され、明らかに開閉の原則が守られていません。
- Liskov置換の原則:Liskov置換の原則:基本クラスへのすべての参照は、そのサブクラスのオブジェクトを透過的に使用できる必要があります
- 継承は使用されず、タイプは3番目の割り当てで使用されたため、このルールは適用されませんでした。
- デメテルの法則:デメテルの法則:「見知らぬ人」ではなく、直接の友達とのみ話してください。
- この設計原則は守られておらず、情報の送信にサードパーティが使用されていないため、高度な結合につながります
- インターフェース分離の原則:インターフェース分離の原則:
1.クライアントは、必要のないインターフェースに依存するべきではありません。
2.クラス間の依存関係は、最小のインターフェイスで確立する必要があります。- 継承と同様に未使用のインターフェースは、結合の度合いを高めます。
- 依存関係の逆転の原則:依存関係の逆転の原則:
1.上位層のモジュールは下位レベルのモジュールに依存してはならず、すべて抽象化に依存する必要があります。
2.抽象化は詳細に依存するべきではなく、詳細は抽象化に依存するべきです。- 3番目のジョブでは、上位レベルのモジュールが下位レベルのモジュールに依存しており、依存関係の逆転の原則に違反しています。抽象化の欠如により、結合の度合いが増加します