经典进程同步问题(Java实现)
maven 依赖:(使用 lombok 简化开发)
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
1、实现 PV 操作
package Common;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Semaphore {
private int count;
public synchronized void P(){
count--;
if (count >= 0) {
return;
} else {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void V(){
count++;
if (count > 0) {
return;
} else {
this.notify();
}
}
}
2、生产者、消费者问题
-
Good
import lombok.ToString; @ToString public class Good { private final String goodName; public static Integer goodId = 0; public Good(String producerName) { this.goodName = producerName+ " 生产的第 " + goodId + "产品"; } }
-
Producer
public class Producer extends Thread{ private Good good; public Producer(String name) { super(name); } private void produceGood() throws InterruptedException { sleep((int) (Math.random() * Buffer.PRODUCER_SPEED)); Buffer.mutex_good_id.P(); if (Good.goodId < Buffer.PRODUCE_GOOD_NUM) { Good.goodId++; } else { this.stop(); } Buffer.mutex_good_id.V(); good = new Good(getName()); } public void putGood() throws InterruptedException { produceGood(); Buffer.empty.P(); Buffer.mutex.P(); for (int i = 0; i < Buffer.BUFFER_SIZE; i++) { if (Buffer.buffer[i] == null) { Buffer.buffer[i] = good; System.out.println(getName() + " 生产了 " + Buffer.buffer[i]); break; } } Buffer.mutex.V(); Buffer.full.V(); } @Override public void run() { while (true) { try { putGood(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
-
Consumer
public class Consumer extends Thread{ private Integer consumeGoodNum = 0; public Consumer (String name) { super(name); } private void consumeGood() throws InterruptedException { sleep((int) (Math.random() * Buffer.CONSUMER_SPEED)); } public void getGood() throws InterruptedException { Buffer.full.P(); Buffer.mutex.P(); for (int i = 0; i < Buffer.BUFFER_SIZE; i++) { if (Buffer.buffer[i] != null) { System.out.println("\t\t\t\t\t\t\t\t\t\t\t\t\t\t" + getName() + " 消费了 " + Buffer.buffer[i]); Buffer.buffer[i] = null; break; } } Buffer.mutex.V(); Buffer.empty.V(); consumeGood(); } @Override public void run() { while (true){ try { getGood(); } catch (InterruptedException e) { e.printStackTrace(); } Buffer.mutex_consume_num.P(); if (consumeGoodNum >= Buffer.PRODUCE_GOOD_NUM){ this.stop(); } consumeGoodNum ++; Buffer.mutex_consume_num.V(); } } }
-
Buffer
import Common.Semaphore; public class Buffer { public static final int BUFFER_SIZE = 15; public static final int PRODUCE_GOOD_NUM = 30; public static Good[] buffer = new Good[BUFFER_SIZE]; public static final int PRODUCER_SPEED = 2000; public static final int CONSUMER_SPEED = 2000; public static Semaphore mutex = new Semaphore(1); public static Semaphore mutex_good_id = new Semaphore(1); public static Semaphore mutex_consume_num = new Semaphore(1); public static Semaphore empty = new Semaphore(BUFFER_SIZE); public static Semaphore full = new Semaphore(0); public static void main(String[] args) { Thread producer1 = new Producer("生产者一"); Thread producer2 = new Producer("生产者二"); Thread producer3 = new Producer("生产者三"); Thread producer4 = new Producer("生产者四"); Thread comsumer1 = new Consumer("消费者一"); Thread comsumer2 = new Consumer("消费者二"); producer1.start(); producer2.start(); producer3.start(); producer4.start(); comsumer1.start(); comsumer2.start(); } }
-
运行结果 (自行配合生产者、与消费者的生产、消费速度)
生产者四 生产了 Good(goodName=生产者四 生产的第 1产品) 消费者一 消费了 Good(goodName=生产者四 生产的第 1产品) 生产者二 生产了 Good(goodName=生产者二 生产的第 2产品) 消费者二 消费了 Good(goodName=生产者二 生产的第 2产品) 生产者四 生产了 Good(goodName=生产者四 生产的第 3产品) 生产者一 生产了 Good(goodName=生产者一 生产的第 4产品) 生产者三 生产了 Good(goodName=生产者三 生产的第 5产品) 生产者一 生产了 Good(goodName=生产者一 生产的第 6产品) 消费者二 消费了 Good(goodName=生产者四 生产的第 3产品) 消费者一 消费了 Good(goodName=生产者一 生产的第 4产品) 生产者四 生产了 Good(goodName=生产者四 生产的第 7产品) 生产者三 生产了 Good(goodName=生产者三 生产的第 8产品) 消费者二 消费了 Good(goodName=生产者四 生产的第 7产品) 消费者二 消费了 Good(goodName=生产者三 生产的第 8产品) 生产者四 生产了 Good(goodName=生产者四 生产的第 9产品) 生产者二 生产了 Good(goodName=生产者二 生产的第 10产品) 消费者一 消费了 Good(goodName=生产者四 生产的第 9产品) 生产者三 生产了 Good(goodName=生产者三 生产的第 11产品) 生产者一 生产了 Good(goodName=生产者一 生产的第 12产品) 消费者二 消费了 Good(goodName=生产者三 生产的第 11产品) 消费者二 消费了 Good(goodName=生产者二 生产的第 10产品) 消费者一 消费了 Good(goodName=生产者三 生产的第 5产品) 生产者一 生产了 Good(goodName=生产者一 生产的第 13产品) 生产者一 生产了 Good(goodName=生产者一 生产的第 14产品) 生产者四 生产了 Good(goodName=生产者四 生产的第 15产品) 生产者四 生产了 Good(goodName=生产者四 生产的第 16产品) 生产者二 生产了 Good(goodName=生产者二 生产的第 17产品) 生产者三 生产了 Good(goodName=生产者三 生产的第 18产品) 生产者一 生产了 Good(goodName=生产者一 生产的第 19产品) 生产者三 生产了 Good(goodName=生产者三 生产的第 20产品) 消费者二 消费了 Good(goodName=生产者一 生产的第 13产品) 生产者二 生产了 Good(goodName=生产者二 生产的第 21产品) 消费者一 消费了 Good(goodName=生产者二 生产的第 21产品) 生产者三 生产了 Good(goodName=生产者三 生产的第 22产品) 消费者二 消费了 Good(goodName=生产者三 生产的第 22产品) 生产者四 生产了 Good(goodName=生产者四 生产的第 23产品) 生产者三 生产了 Good(goodName=生产者三 生产的第 24产品) 消费者二 消费了 Good(goodName=生产者四 生产的第 23产品) 生产者三 生产了 Good(goodName=生产者三 生产的第 25产品) 生产者一 生产了 Good(goodName=生产者一 生产的第 26产品) 生产者四 生产了 Good(goodName=生产者四 生产的第 27产品) 生产者二 生产了 Good(goodName=生产者二 生产的第 28产品) 消费者一 消费了 Good(goodName=生产者三 生产的第 25产品) 生产者三 生产了 Good(goodName=生产者三 生产的第 29产品) 生产者四 生产了 Good(goodName=生产者四 生产的第 30产品) 消费者二 消费了 Good(goodName=生产者三 生产的第 29产品) 消费者一 消费了 Good(goodName=生产者一 生产的第 14产品) 消费者一 消费了 Good(goodName=生产者四 生产的第 15产品) 消费者一 消费了 Good(goodName=生产者一 生产的第 6产品) 消费者二 消费了 Good(goodName=生产者一 生产的第 12产品) 消费者二 消费了 Good(goodName=生产者四 生产的第 16产品) 消费者二 消费了 Good(goodName=生产者二 生产的第 17产品) 消费者一 消费了 Good(goodName=生产者三 生产的第 18产品) 消费者一 消费了 Good(goodName=生产者一 生产的第 19产品) 消费者一 消费了 Good(goodName=生产者三 生产的第 20产品) 消费者二 消费了 Good(goodName=生产者三 生产的第 24产品) 消费者二 消费了 Good(goodName=生产者一 生产的第 26产品) 消费者一 消费了 Good(goodName=生产者四 生产的第 27产品) 消费者一 消费了 Good(goodName=生产者二 生产的第 28产品) 消费者二 消费了 Good(goodName=生产者四 生产的第 30产品)
3、哲学家就餐问题
-
Philosopher
import lombok.Data; @Data public class Philosopher extends Thread { private int philosopherId; public Philosopher(String name) { super(name); } public Philosopher(int philosopherId) { this.philosopherId = philosopherId; } public void think(){ try { sleep((int) (Math.random() * Table.PHILOSOPHER_THINK_TIME)); } catch (InterruptedException e) { e.printStackTrace(); } } public void eat() throws InterruptedException { Table.chopstick[philosopherId].P(); Table.chopstick[(philosopherId+1)%Table.PHILOSOPHER_NUM].P(); System.out.println( philosopherId + " 号哲学家拿起 " + philosopherId + " 和 " + (philosopherId+1) + " 号筷子 开始就餐"); sleep((int) (Math.random() * Table.PHILOSOPHER_EAT_TIME)); Table.chopstick[philosopherId].V(); Table.chopstick[(philosopherId+1)%Table.PHILOSOPHER_NUM].V(); } @Override public void run() { while (true) { think(); try { eat(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
-
Table
import Common.Semaphore; public class Table { public static final int PHILOSOPHER_NUM = 5; public static final int PHILOSOPHER_THINK_TIME = 10000; public static final int PHILOSOPHER_EAT_TIME = 5000; public static Semaphore[] chopstick = new Semaphore[PHILOSOPHER_NUM]; public static void main(String[] args) { for (int i = 0; i < PHILOSOPHER_NUM; i++) { chopstick[i] = new Semaphore(1); } Philosopher philosophers[] = new Philosopher[PHILOSOPHER_NUM]; for (int i = 0; i < PHILOSOPHER_NUM; i++) { philosophers[i] = new Philosopher(i); philosophers[i].start(); } } }
-
运行结果
2 号哲学家拿起 2 和 3 号筷子 开始就餐 4 号哲学家拿起 4 和 5 号筷子 开始就餐 0 号哲学家拿起 0 和 1 号筷子 开始就餐 4 号哲学家拿起 4 和 5 号筷子 开始就餐 1 号哲学家拿起 1 和 2 号筷子 开始就餐 3 号哲学家拿起 3 和 4 号筷子 开始就餐 0 号哲学家拿起 0 和 1 号筷子 开始就餐 2 号哲学家拿起 2 和 3 号筷子 开始就餐 .....
4、读者、写者问题
-
Reader
public class Writer extends Thread { public Writer (String name) { super(name); } public void write() throws InterruptedException { Main.wmutex.P(); System.out.println(getName() + ": 编辑 "); sleep((int) (Math.random() * Main.WRITE_TIME)); Main.wmutex.V(); } @Override public void run() { while (true) { try { write(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
-
Writer
public class Writer extends Thread { public Writer (String name) { super(name); } public void write() throws InterruptedException { Main.wmutex.P(); System.out.println(getName() + ": 编辑 "); sleep((int) (Math.random() * Main.WRITE_TIME)); Main.wmutex.V(); } @Override public void run() { while (true) { try { write(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
-
Main
import Common.Semaphore; public class Main { public static Semaphore rmutex = new Semaphore(1); public static Semaphore wmutex = new Semaphore(1); public static final int READ_TIME = 5000; public static final int WRITE_TIME = 5000; public static int readCount = 0; public static void main(String[] args) { Thread reader1 = new Reader("读者一"); Thread reader2 = new Reader("读者二"); Thread writer1 = new Writer("写者一"); reader1.start(); reader2.start(); writer1.start(); } }
-
运行结果
写者一: 编辑 读者一: 读书 读者二: 读书 读者一: 读书 写者一: 编辑 读者二: 读书 读者一: 读书 写者一: 编辑