java的线程读写操作(共享跟互斥)

java的线程读写操作(共享和互斥)

       最近看了看java的线程操作的方法的内容,照书上写了一下代码试了试,主要的内容是我们固定输入一段字符串,然后依次按顺序读每一个字符,创建6个读操作的线程和2个写进程的进程,操作的方式是,可以同时读,但是不可以同时写,而且在读的时候不可以写,写的时候不可以读!

      erlang多是利用同步异步消息来处理数据问题,所以有的时候自己经常会忘记锁了以后要解锁!!!!

      

package test1;

public class Main {
	public static void main(String[] args){
		Data data = new Data(10);		//创建Data类的实例
		/**启动6个读操作线程**/
		new ReaderThread(data).start();
		new ReaderThread(data).start();
		new ReaderThread(data).start();
		new ReaderThread(data).start();
		new ReaderThread(data).start();
		new ReaderThread(data).start();
		/**启动2个写操作线程**/
		new WriterThread(data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ").start();
		new WriterThread(data, "abcdefghijklmnopqrstuvwxyz").start();
	}
}

 

package test1;

/**数据操作类**/
public class Data {
		private final char[] buffer;	//新建一个缓存字符串数组
		private final ReadWriteLock lock = new ReadWriteLock();		 //创建一个ReadWriteLock类的对象lock
		
		/**Data类的构造函数,输入一个size**/
		public Data(int size){	
			this.buffer = new char[size];	//为buffer对象申请size大小的空间
			for(int i = 0; i < buffer.length; i++){
				buffer[i] = '*';			//将buffer内初始为*号
			}
		}
		
		/**读操作方法(主要完成的是锁操作)**/
		public char[] read() throws InterruptedException{
			lock.readLock();	//对lock实例进行读锁操作
			try{
				return doRead();	//读操作
			}finally{
				lock.readUnlock();	//对lock实例读解锁操作
			}
		}
		
		/**写操作方法(主要完成的是锁操作)**/
		public void write(char c) throws InterruptedException{
			lock.writeLock();	//对lock实例进行写锁操作
			try{
				doWrite(c);		//进行写操作
			}finally{
				lock.writeUnlock();	//进行写解锁
			}
		}
		
		/**读操作主要逻辑**/
		private char[] doRead(){
			char[] newbuf = new char[buffer.length];	//创建一个大小为buffer.length的newbuf对象
			for(int i = 0; i < buffer.length; i++){
				newbuf[i] = buffer[i];					//数据拷贝
			}
			slowly();									//延迟操作
			return newbuf;								//返回newbuf
		}
		
		/**写操作主要逻辑**/
		private void doWrite(char c){
			for(int i = 0; i < buffer.length; i++){
				buffer[i] = c;							//将buffer中的数据替换成字符串c
				slowly();								//延迟操作
			}
		}
		
		/**模拟时间操作**/
		private void slowly(){
			try{
				Thread.sleep(0);						//延迟50毫秒
			}catch(InterruptedException e){
				
			}
		}
}

 

package test1;

/**读写锁操作类**/
public final class ReadWriteLock {
	private int readingReaders = 0;   //阅读者的数量
	private int waitingWriters = 0;   //等待的编辑者数量
	private int writingWriters = 0;   //编辑者的数量
	private boolean preferWriter = true;   //是否正在被编辑
	
	/**读锁**/
	public synchronized void readLock() throws InterruptedException{
		//如果是 编写者的数量大于0  并且 等待的编写者大于0或者正在被编写  那么该进程等待
		while(writingWriters > 0 || (preferWriter && waitingWriters >0)){
			//等待操作
			wait();
		}
		//读写者加1可以读
		readingReaders++;
	}
	
	/**读解锁**/
	public synchronized void readUnlock(){
		readingReaders--;	//读者减1 解锁读
		preferWriter = true;	//可以写
		notifyAll();	//唤醒其他进程操作
	}
	
	/**写锁**/
	public synchronized void writeLock() throws InterruptedException{
		waitingWriters++; //编辑者加1
		try{
			//如果读者大于0 并且 编写者大于0
			while(readingReaders > 0 || writingWriters > 0){
				//等待操作
				wait();
			}
		}finally{
			waitingWriters--;	//最终等待者减1
		}
		writingWriters++;	//编写者加1
	}
	
	/**编写者解锁**/
	public synchronized void writeUnlock(){
		writingWriters --;	//编辑者减1
		preferWriter = false;	//没有被编辑
		notifyAll();	//唤醒其他的进程
	}
}

 

package test1;
import java.util.Random;

/**写操作线程类**/
public class WriterThread extends Thread {
	private static final Random random = new Random();	//random的实例
	private final Data data;	//创建一个Data的实例
	private final String filler;	//创建一个filler的字符串
	private int index = 0;			//创建一个index类为0
	
	/**WriterThread类构造器**/
	public WriterThread(Data data, String filler){
		this.data = data;
		this.filler = filler;
	}
	
	/**启动线程实现run方法**/
	public void run(){
		try{
			while(true){
				char c = nextchar();	//返回filler中的下一个字符
				data.write(c);			//将字符c写入
				Thread.sleep(random.nextInt(3000));	//1~3000随机休眠
			}
		}catch (InterruptedException e){
			
		}
	}
	
	/**实现nextchar的方法,指定索引位置的char值**/
	private char nextchar(){
		char c = filler.charAt(index);	//字符串的位置
		index++;						//index的值递增
		if(index >= filler.length()){
			index = 0;					//如果index的值大于字符串的长度则index为0
		}
		return c;
	}
}

 

package test1;

/**读操作的线程类**/
public class ReaderThread extends Thread{
	private final Data data;			//创建一个Data的实例
	
	/**该类的构造器**/
	public ReaderThread(Data data){
		this.data = data;
	}
	
	/**实现run方法**/
	public void run(){
		try{
			while(true){
				char[] readbuf = data.read();		//读操作
				System.out.println(Thread.currentThread().getName() + "reads"
						+ String.valueOf(readbuf));	//打印操作
			}
		}catch (InterruptedException e){
			
		}
	}
}

        这个程序虽然只是简单的多线程编程的一个例子,但是只要将main函数以及模拟休息的部分和输入的buffer参数稍作修改就可以完成一些真正意义上的并发锁的操作

 

       这里还是有些要注意的:

       1.你想要保护什么就锁什么!

       2.完成操作一定要解锁!

 

测试例子:(比较多,总之在读完所有的字符以前不出现混乱读取)
java的线程读写操作(共享跟互斥)