做爲操做系統中的最基本模型,在面試中被要求書寫的可能性仍是很大的,若是隻是僞碼,這仍是一個簡單的問題,可是要你具體實現呢?你會使用什麼樣的方式來實現這件事情呢?java
什麼是生產者、消費者問題?面試
意思很簡單,就是生產者給生產鏈生產,而消費者從生產鏈中拿出。那關鍵點已經出來了,問題就在於怎麼處理這一條生產鏈( 正規叫法應該叫緩衝區)?// 變量
list = buffer[n] // 生產鏈,容量爲n
,mutex = 1 // 互斥使用生產鏈
,empty = n // 消費後剩餘
,full = 0 // 生產後容量
// 兩個運做對象:及對應動做
producer:product // 生產者生產
consumer:consume // 消費者消費
// 兩個動做
product{
wait(empty) // 生產鏈不滿
wait(mutex)
// 生產
signal(mutex)
signal(full) // 給生產鏈加一個產品
}
consumer{
wait(full) // 生產鏈不爲空
wait(mutex)
// 消費
signal(mutex)
signal(empty) // 生產鏈中的產品又被消耗
}
複製代碼
class ProducerAndConsumer {
private final int MAX_LEN = 10;
private Queue<Integer> queue = new LinkedList<Integer>();
Semaphore producer = new Semaphore(0);
Semaphore consumer = new Semaphore(MAX_LEN);
Semaphore lock = new Semaphore(1);
// 生產者
class Producer extends Thread {
@Override
public void run() {
while (true) {
try {
consumer.acquire(); // 可消費的數量未滿
lock.acquire(); // 臨界區
queue.add(1);
System.out.println("consumer size:" + queue.size());
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.release();
producer.release();
}
}
}
}
// 消費者
class Consumer extends Thread {
@Override
public void run() {
while (true) {
try {
producer.acquire(); // 還剩餘產品
lock.acquire(); // 臨界區
queue.remove();
System.out.println("consumer size:" + queue.size());
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.release();
consumer.release();
}
}
}
}
public static void main(String[] args) {
ProducerAndConsumer producerAndConsumer = new ProducerAndConsumer();
Producer producer = producerAndConsumer.new Producer();
Consumer consumer = producerAndConsumer.new Consumer();
producer.start();
consumer.start();
}
}
複製代碼
五把叉子,五我的,若是每一個人都拿起了叉子,那麼整桌的人必然就沒飯吃了,哲學家問題思考的就是這樣的一個問題。bash
// 變量
forks = {1, 1, 1, 1, 1} // 暫定爲5人
// 一個被運做對象:以及動做
fork:handle、release
Philosopher:thinking、eating
// 動做,eating和thinking是兩個Thread.sleep完成
handle {
// 左右手只要有一隻被拿起,就須要等待
// 若是不等帶,就可能每一個人只拿一隻
while(forks[postion] == 0 || forks[(position + 1) % 5] == 0){
wait() // 等待
}
forks[postion] == 0;
forks[(position + 1) % 5] == 0;
}
release {
// 吃完之後把東西放下
forks[postion] == 1;
forks[(position + 1) % 5] == 1;
}
複製代碼
public class PhilosopherEat {
class Philosopher extends Thread {
private String name;
private Fork fork;
public Philosopher(String name, Fork fork) {
super(name);
this.name = name;
this.fork = fork;
}
@Override
public void run() {
// 哲學家須要完成要的一系列動做
while (true) {
thinking();
fork.takeFork();
eating();
fork.putFork();
}
}
public void eating() {
System.out.println("I am Eating:" + name);
try {
//模擬吃飯
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void thinking() {
System.out.println("I am Thinking:" + name);
try {
//模擬思考
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Fork{
// 5根筷子
private boolean[] used={false,false,false,false,false,false};
public synchronized void takeFork(){
String name = Thread.currentThread().getName();
int i = Integer.parseInt(name);
// 若是左右手有一隻正被使用就等待
while(used[i]||used[(i+1)%5]){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
used[i ]= true;
used[(i+1)%5]=true;
}
// 同時釋放左右手的筷子
public synchronized void putFork(){
String name = Thread.currentThread().getName();
int i = Integer.parseInt(name);
used[i ]= false;
used[(i+1)%5]=false;
notifyAll();
}
}
public static void main(String[] args) {
PhilosopherEat philosopher = new PhilosopherEat();
Fork fork = philosopher.new Fork();
philosopher.new Philosopher("0",fork).start();
philosopher.new Philosopher("1",fork).start();
philosopher.new Philosopher("2",fork).start();
philosopher.new Philosopher("3",fork).start();
philosopher.new Philosopher("4",fork).start();
}
}
複製代碼
讀者寫者問題針對的就是咱們的數據問題,你在wps
打開一個文件,又在word
打開一個文件勢必會看到一個只讀的模式會彈出,這就是讀者寫着問題的具體表現了。ide
// 變量
readCount // 當前讀書的人數
,readLock // 讀者鎖
,writeLock // 寫者鎖
// 兩個對象:及其動做
Reader:read
Writer:write
// 動做
read{
p(readLock)
if(readCount == 0) p(writeLock) // 第一個讀者進入後,就不可修改
readCount++
v(readLock)
// 。。。讀書
p(readLock)
readCount--
if(readCount == 0) v(writeLock) // 最後一個讀者走後,能夠開始修改
v(readLock)
}
write{
p(writeLock)
// 。。。修改
v(writeLock)
}
複製代碼
import java.util.concurrent.Semaphore;
public class ReaderAndWriter {
public static void main(String[] args) {
// 實現寫者與寫者間、讀者與寫者間互斥
Semaphore wmutex = new Semaphore(1);
// 用於改變 readCount 變量時實現互斥
Semaphore rmutex = new Semaphore(1);
for (int i = 0; i < 3; ++i) {
new Reader(rmutex, wmutex).start();
new Writer(wmutex).start();
}
}
}
class Reader extends Thread {
private static int total = 0;
private int id;
private Semaphore rmutex, wmutex;
private static int readCount = 0;
public Reader(Semaphore rmutex, Semaphore wmutex) {
id = ++total;
this.rmutex = rmutex;
this.wmutex = wmutex;
}
@Override
public void run() {
while (true) {
try {
rmutex.acquire();
// 只有第一個讀者進程須要執行 wmutex.p()
if (readCount == 0) wmutex.acquire();
readCount++;
System.out.println(id + " 號讀者在讀");
} catch (Exception e) {
} finally {
rmutex.release();
}
// 模擬讀書
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 讀書人出去了
try {
rmutex.acquire();
readCount--;
System.out.println(id + " 號讀者結束閱讀:當前還剩 " + readCount + " 位讀者在讀");
if (readCount == 0) wmutex.release();
} catch (Exception e) {
} finally {
rmutex.release();
}
}
}
}
class Writer extends Thread {
private static int total = 0;
private int id;
private Semaphore wmutex;
public Writer(Semaphore wmutex) {
id = ++total;
this.wmutex = wmutex;
}
@Override
public void run() {
while (true) {
try {
wmutex.acquire();
// 執行寫操做
System.out.println(id + " 號寫者正在寫");
wmutex.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 線程休眠一段時間,總不會一直改的
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
複製代碼
以上就是個人學習成果,若是有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。post
相關文章推薦:學習