Leetcode04--給定兩個大小為 m 和 n 的正序(從小到大)陣列 nums1 和 nums2。請你找出並返回這兩個正序陣列的中位數。
阿新 • • 發佈:2021-02-16
在實際的軟體開發過程中,經常會碰到:某個模組負責產生資料,然後這些資料由另一個模組來負責處理(此處的模組是廣義的,可以是類、函式、執行緒、程序等)。產生資料的模組,就稱為生產者;而處理資料的模組,就稱為消費者。另外還需要有一個緩衝區處於生產者和消費者之間,作為一箇中介。生產者把資料放入緩衝區,而消費者從緩衝區取出資料。
比如你要寄一封信,大致過程如下:
1、你把信寫好——相當於生產者製造資料 2、你把信放入郵筒——相當於生產者把資料放入緩衝區 3、郵遞員把信從郵筒取出——相當於消費者把資料取出緩衝區 4、郵遞員把信拿去郵局做相應的處理——相當於消費者處理資料
這個緩衝區有什麼用?為什麼不讓生產者直接呼叫消費者的某個函式,直接把資料傳遞過去?
優點:
1、解耦
如果讓生產者直接呼叫消費者的某個方法,那麼生產者對於消費者就會產生依賴(也就是耦合)。而如果兩者都依賴於某個緩衝區,兩者之間不直接依賴,耦合也就相應降低了。
2、支援併發
生產者和消費者可以是兩個獨立的併發主體,生產者把製造出來的資料往緩衝區一丟,就可以再去生產下一個資料。基本上不用依賴消費者的處理速度。如果是生產者直接呼叫消費者的某個方法的話,由於函式呼叫是同步的(或者叫阻塞的),在消費者的方法沒有返回之前,生產者只能一直等造成浪費。事實上,最初生產者和消費者模式的出現就是為了併發問題。
3、支援忙閒不均
即適用於製造資料的速度時快時慢時。當資料製造快的時候,消費者來不及處理,未處理的資料可以暫時存在緩衝區中。等生產者的製造速度慢下來,消費者再慢慢處理掉。
通過Object類中的wait()、notify()、notifyAll()來實現生產者和消費者模式。
1.利用緩衝區實現:管程法
package com.yang.PC;
//生產者消費者模型 --> 利用緩衝區解決:管程法
public class Buffer {
public static void main(String[] args) {
Syncontainer container = new Syncontainer ();
new Productor(container).start();
new Consumer(container).start();
}
}
//生產者
class Productor extends Thread{
Syncontainer container;
public Productor(Syncontainer container){
this.container = container;
}
//生產
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("生產了"+i+"雞");
container.push(new Chicken(i));
}
}
}
//消費者
class Consumer extends Thread{
Syncontainer container;
public Consumer(Syncontainer container){
this.container = container;
}
//消費
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("消費了第"+container.pop().id+"雞");
}
}
}
//緩衝區
class Syncontainer{
//定義容器大小
Chicken[] chickens = new Chicken[10];
int count = 0; //容器計數器
//生產者將產品放入容器
public synchronized void push(Chicken chicken){
//如果容器滿了,就需要等待消費者消費
if (count ==chickens.length){
try {
this.wait(); //通知並等待消費者消費
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果沒有滿,則將產品丟入容器
chickens[count] = chicken;
count++;
//裝滿了,通知消費者消費
this.notifyAll();
}
//消費者消費產品
public synchronized Chicken pop(){
//判斷容器中是否有雞
if (count == 0){
try {
this.wait(); //等待生產者生產
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果容器中有雞
count--;
Chicken chicken = chickens[count];
//吃完了,通知生產者生產
this.notifyAll();
return chicken;
}
}
//產品
class Chicken{
int id; //產品id
public Chicken(int id){
this.id = id;
}
}
2.利用標誌位實現:訊號燈法
package com.yang.PC;
public class Flag {
public static void main(String[] args) {
TV tv = new TV();
new Player(tv).start();
new Watcher(tv).start();
}
}
//演員-->生產者
class Player extends Thread{
TV tv;
public Player(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
if (i%2 == 0){
this.tv.play("胸口碎大石");
}else {
this.tv.play("舉重");
}
}
}
}
//觀眾-->消費者
class Watcher extends Thread{
TV tv;
public Watcher(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
tv.watch();
}
}
}
//產品-->節目
class TV{
//演員表演,觀眾等待 T
//觀眾觀看,演員等待 F
String show; //節目
boolean flag = true;
//表演
public synchronized void play(String show){
if (!flag){
try {
this.wait(); //演員等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演員表演了"+show);
//通知觀眾觀看
this.notifyAll();
this.show = show;
this.flag = !this.flag;
}
//觀看
public synchronized void watch() {
if (flag){
try {
this.wait(); //等待觀看
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("觀看了"+show);
//通知演員表演
this.notifyAll();
this.flag = !this.flag;
}
}
總結:生產者和消費者模式是通過一個容器(緩衝區)來解決生產者和消費者的強耦合關係。生產者即產生資料的模組,消費者是處理資料的模組。位於它們之間的緩衝區可以使得生產者生成資料後無需等待消費者索取,消費者也無需直接向生產者索要資料。這樣做最大的好處就是可以實現解耦。此外還可以支援併發和忙閒不均。