MybatisPlus分頁條件查詢
程序與執行緒
有一定基礎的小夥伴們肯定都知道程序和執行緒。
程序是什麼呢?
直白地講,程序就是應用程式的啟動例項。比如我們執行一個遊戲,開啟一個軟體,就是開啟了一個程序。
程序擁有程式碼和開啟的檔案資源、資料資源、獨立的記憶體空間。
執行緒又是什麼呢?
執行緒從屬於程序,是程式的實際執行者。一個程序至少包含一個主執行緒,也可以有更多的子執行緒。
執行緒擁有自己的棧空間。
有人給出了很好的歸納:
對作業系統來說,執行緒是最小的執行單元,程序是最小的資源管理單元。
無論程序還是執行緒,都是由作業系統所管理的。
協程
執行緒之間是如何進行協作的呢?
最經典的例子就是生產者/消費者模式:
若干個生產者執行緒向佇列中寫入資料,若干個消費者執行緒從佇列中消費資料。
我們可以舉個簡單的例子:
public class ProducerConsumerTest { public static void main(String args[]) { final Queue<Integer> sharedQueue = new Queue(); Thread producer = new Producer(sharedQueue); Thread consumer = new Consumer(sharedQueue); producer.start(); consumer.start(); } }class Producer extends Thread { private static final int MAX_QUEUE_SIZE = 5; private final Queue sharedQueue; public Producer(Queue sharedQueue) { super(); this.sharedQueue = sharedQueue; } @Override public void run() { for (int i = 0; i < 100; i++) {synchronized (sharedQueue) { while (sharedQueue.size() >= MAX_QUEUE_SIZE) { System.out.println("佇列滿了,等待消費"); try { sharedQueue.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } sharedQueue.add(i); System.out.println("進行生產 : " + i); sharedQueue.notify(); } } } } class Consumer extends Thread { private final Queue sharedQueue; public Consumer(Queue sharedQueue) { super(); this.sharedQueue = sharedQueue; } @Override public void run() { while (true) { synchronized (sharedQueue) { while (sharedQueue.size() == 0) { try { System.out.println("佇列空了,等待生產"); sharedQueue.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int number = sharedQueue.poll(); System.out.println("進行消費 : " + number); sharedQueue.notify(); } } } }
1.定義了一個生產者類,一個消費者類。
2.生產者類迴圈100次,向同步(阻塞)隊列當中插入資料。
3.消費者迴圈監聽同步佇列,當佇列有資料時拉取資料。
4.如果佇列滿了(達到5個元素),生產者阻塞。
5.如果佇列空了,消費者阻塞。
上面的程式碼正確地實現了生產者/消費者模式,但是卻並不是一個高效能的實現。為什麼效能不高呢?原因如下:
1.涉及到同步鎖。
2.涉及到執行緒阻塞狀態和可執行狀態之間的切換。
3.涉及到執行緒上下文的切換。
以上涉及到的任何一點,都是非常耗費效能的操作。
所以這裡就會用到協程的概念
協程,英文Coroutines,是一種比執行緒更加輕量級的存在。正如一個程序可以擁有多個執行緒一樣,一個執行緒也可以擁有多個協程。
最重要的是,協程不是被作業系統核心所管理,而完全是由程式所控制(也就是在使用者態執行)。
這樣帶來的好處就是效能得到了很大的提升,不會像執行緒切換那樣消耗資源。
既然協程這麼好,它到底是怎麼來使用的呢?
def consumer(): while True: number = yield print('開始消費',number) consumer = consumer() next(consumer) for num in range(100): print('開始生產',num) consumer.send(num)
這段程式碼十分簡單,即使沒用過python的小夥伴應該也能基本看懂。
程式碼中建立了一個叫做consumer的協程,並且在主執行緒中生產資料,協程中消費資料。
其中yield是python當中的語法。當協程執行到yield關鍵字時,會暫停在那一行,等到主執行緒呼叫send方法傳送了資料,協程才會接到資料繼續執行。
但是,yield讓協程暫停,和執行緒的阻塞是有本質區別的。協程的暫停完全由程式控制,執行緒的阻塞狀態是由作業系統核心來進行切換。
因此,協程的開銷遠遠小於執行緒的開銷。