基本原理来自《现代操作系统》我用java给重写了一边。多线程经验不多,有问题多指教。
生产者消费者问题
有一点需要特别注意一下,如果只有一个生产者一个消费者可以使用notify。如果有多个生产者和消费者则需要使用notifyall否则会产生死锁。
这里使用wait和notify方法实现也可以使用其他方式。日后或许会在补充。
package ipc;
import java.util.Random;
public class ProductorandConsumerWithWait {
static final int N = 10;
static final productor p1 = new productor();
static final productor p2 = new productor();
static final consumer c = new consumer();
static final monitor mon = new monitor();
public static void main(String[] args) {
p1.start();
p2.start();
c.start();
}
static class productor extends Thread{
@Override
public void run(){
int item;
while(true){
item = productor_item();
mon.insert(item);
}
}
private int productor_item() {
Random random = new Random();
int item = random.nextInt();
System.out.println("生产 :"+item);
return item;
}
}
static class consumer extends Thread{
@Override
public void run(){
int item;
while(true){
item = mon.remove();
consum_item(item);
}
}
private void consum_item(int item) {
System.out.println("消费 :"+item);
}
}
static class monitor{
private int[] buffer = new int[N];
private int count = 0, lo = 0, hi = 0;
public synchronized void insert(int val){
if(count == N)
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
buffer[hi] = val;
hi = (hi+1)/N;
count = count +1;
if(count == 1) notifyAll();
}
public synchronized int remove(){
if(count ==0)
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int val = buffer[lo];
lo = (lo+1)/N;
count--;
if(count == N-1) notifyAll();
return val;
}
}
}
哲学家就餐
没有特别需要注意的。原书中是使用互斥锁,如果使用java中间的lock应该更符合原意,这里使用的是synchronized不过就目前来看效果是一样的。
package ipc;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class PhilosopherDining {
static final private int THINKING = 0;
static final private int HUNGRY = 1;
static final private int EATING = 2;
static final private int NUMBER = 5;
int[] state = new int[NUMBER];
private Semaphore[] s = new Semaphore[NUMBER];
public void takeforks(int i){
take_forks(i);
try {
s[i].acquire();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
s[i].release();
}
}
private synchronized void take_forks(int i){
state[i] = HUNGRY;
test(i);
}
public synchronized void put_forks(int i ){
state[i] = THINKING;
test((i+NUMBER-1)%NUMBER);
test((i+1)%NUMBER);
}
private void test(int i){
if(state[i] == HUNGRY && state[(i+NUMBER-1)%NUMBER] != EATING && state[(i+1)%NUMBER] != EATING){
state[i] = EATING;
System.out.println("Philosopher "+i+" is having dinner!");
s[i].release();
}
}
public static void main(String[] args) {
PhilosopherDining pd = new PhilosopherDining();
for(int i = 0 ; i< NUMBER ; i++){
pd.s[i] = new Semaphore(1);
}
ExecutorService pool = Executors.newFixedThreadPool(5);
for(int i = 0 ;i < NUMBER ; i++){
Runner runner = new Runner(pd,i);
pool.submit(runner);
}
}
}
package ipc;
public class Runner implements Runnable{
private PhilosopherDining ph;
private int i;
public Runner(PhilosopherDining ph,int i){
this.ph = ph;
this.i = i;
}
@Override
public void run() {
while(true){
ph.takeforks(i);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ph.put_forks(i);
}
}
}
读者写者问题
java中有专门的读写类。如果使用ReentrantReadWriteLock,应该更科学一些。以后会在补充。
package ipc;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class ReaderandWriter {
Semaphore db = new Semaphore(1);
int rc = 0;
Semaphore hasWriter = new Semaphore(1);
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(7);
ReaderandWriter rw = new ReaderandWriter();
Reader r1 = new Reader(rw);
Reader r2 = new Reader(rw);
Reader r3 = new Reader(rw);
Reader r4 = new Reader(rw);
Reader r5 = new Reader(rw);
Writer w1 = new Writer(rw);
Writer w2 = new Writer(rw);
pool.submit(r1);
pool.submit(r2);
pool.submit(r3);
pool.submit(r4);
pool.submit(r5);
pool.submit(w1);
pool.submit(w2);
}
}
package ipc;
public class Reader implements Runnable{
private ReaderandWriter rw;
public Reader(ReaderandWriter rw) {
this.rw = rw;
}
@Override
public void run() {
while(true){
try {
addrc();
System.out.println(rw.rc + "is reading");
Thread.sleep(1);
cutrc();
System.out.println(rw.rc+"use data");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void cutrc() {
synchronized (rw) {
rw.rc--;
if(rw.rc == 0){
rw.db.release();
}
}
}
private void addrc() throws InterruptedException {
synchronized (rw) {
if(!rw.hasWriter.tryAcquire()){
rw.db.release();
rw.hasWriter.acquire();
rw.db.acquire();
}
rw.rc++;
if(rw.rc ==1){
rw.db.acquire();
}
rw.hasWriter.release();
}
}
}
package ipc;
public class Writer implements Runnable{
private ReaderandWriter rw;
public Writer(ReaderandWriter rw){
this.rw = rw;
}
@Override
public void run() {
while(true){
try {
rw.hasWriter.acquire();
System.out.println("think up data");
Thread.sleep(1);
rw.db.acquire();
System.out.println("write data base");
rw.db.release();
rw.hasWriter.release();
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}