一、原理及说明
1.生产者-消费者问题
1)一组生产者进程生产产品给一组消费者进程消费。一个有n个缓冲区的缓冲池,生产者一次向一个缓冲区中投入消息,消费者从一个缓冲区中取得。生产者——消费者问题实际上是相互合作进程关系的一种抽象。该类问题不允许消费者进程到一个空缓冲区中取产品,同时也不允许生产者进程到一个已满且还没被取走的缓冲区中投放产品。
2)使用一个数组来表示具有n个(0,1,…,n-1)缓冲区的缓冲池。用输入指针in来指示下一个可投放产品的缓冲区,每当生产者进程生产并投放一个产品后,in加1;用一个输出指针out来指示下一个可从中获取产品的缓冲区,每当消费者进程取走一个产品后,out加1。缓冲池是循环数组。
3)可利用互斥信号量mutex实现诸进程对缓冲池的互斥使用;利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲区的数量。
2.读者-写者问题
1)一个数据文件或者记录可被多个进程(或线程)共享。其中,有些进程(或线程)要求读;而另一些进程(或线程)要求能写或者修改。
2)只要求读的进程(或线程)称为“Reader进程”,其他进程(或线程)称为“Witer进程(或线程)”。
3)允许多个Reader进程(或线程)同时读一个共享对象,不允许一个Writer进程(或线程)和其他Reader进程(或线程)或者Writer进程(或线程)同时访问共享对象。
例题:
读者-写者问题
新建一个“input.txt”文件,存放与源程序在同一目录下。分别测试两组数据,文件内容分别为:
第一组数据: 第二组数据:
1 R 3 5 1 W 2 3
2 W 4 5 2 R 3 6
3 R 5 2 3 R 4 2
4 R 6 5 4 W 6 5
5 W 5.1 3 5 R 7 2
代码:
//主类ReaderWriter类
import java.io.*;
import java.util.*;
public class ReaderWriter
{
public static void main(String[] args)
{
Semaphore wmutex = new Semaphore(1);
Semaphore rmutex = new Semaphore(1);
int i;
String s=null;
My m[]=new My[10];
try{
BufferedReader br=new BufferedReader(new FileReader("D:\\JavaProject\\src\\Test\\input.txt"));
for (i=0;(s=br.readLine())!=null;i++)
{
m[i]=new My(s);
System.out.println("线程"+m[i].thread+"是"+m[i].type+"线程,第"+m[i].arrive_time+"秒申请读写操作,操作持续"+m[i].operate_time+"秒");
if (m[i].type.equals("R")){
new Thread(new Reader(rmutex,wmutex,m[i])).start();
}
else {
new Thread(new Writer(wmutex,m[i])).start();
}
}
}
catch(IOException e){}
}
}
//内部类reader
class Reader implements Runnable{
private Semaphore rmutex,wmutex;
My my;
static int readcount = 0;
public Reader(Semaphore rmutex,Semaphore wmutex,My my){
this.rmutex = rmutex;
this.wmutex = wmutex;
this.my = my;
}
@Override
public void run() {
try{
Thread.sleep((int)(1000*my.arrive_time));
}catch (InterruptedException e){e.printStackTrace();}
System.out.println("线程" + my.thread + "申请读操作");
rmutex.p();
if (readcount == 0) wmutex.p();
readcount++;
rmutex.v();
System.out.println("线程" + my.thread + "开始读操作");
try{
Thread.sleep((int)(1000*my.operate_time));
} catch (InterruptedException e){
e.printStackTrace();
}
rmutex.p();
readcount--;
System.out.println("线程" + my.thread + "结束读操作");
if (readcount == 0) wmutex.v();
rmutex.v();
}
}
//内部类writer
class Writer implements Runnable{
private Semaphore wmutex;
My my;
public Writer(Semaphore wmutex,My my){
this.wmutex = wmutex;
this.my = my;
}
@Override
public void run() {
try{
Thread.sleep((int)(1000*my.arrive_time));
}catch (InterruptedException e){e.printStackTrace();}
System.out.println("线程" + my.thread + "申请写操作");
wmutex.p();
System.out.println("线程" + my.thread + "开始写操作");
try{
Thread.sleep((int)(1000*my.operate_time));
}catch (InterruptedException e){e.printStackTrace();}
wmutex.v();
System.out.println("线程" + my.thread + "完成写操作");
}
}
//内部类my
class My
{
int thread;
String type;
double arrive_time;
double operate_time;
My(String s)
{
StringTokenizer st=new StringTokenizer(s);
thread = Integer.parseInt(st.nextToken());
type = st.nextToken();
arrive_time = Double.parseDouble(st.nextToken());
operate_time = Double.parseDouble(st.nextToken());
}
}
Semaphore类
//Semaphore类
public class Semaphore{
private int semValue;
public Semaphore(int semValue) {
this.semValue = semValue;
}
public synchronized void p() {
semValue--;
if (semValue < 0) {
try {
this.wait();//阻塞该进程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void v(){
semValue++;
if (semValue <= 0) {
this.notify();//唤醒被阻塞的进程
}
}
}