java 讀者寫者問題

 讀者—寫者問題(Readers-Writers problem)也是一個經典的併發程序設計問題,是經常出現的一種同步問題。計算機系統中的數據(文件、記錄)常被多個進程共享,但其中某些進程可能只要求讀數據(稱爲讀者Reader);另一些進程則要求修改數據(稱爲寫者Writer)。就共享數據而言,Reader和Writer是兩組併發進程共享一組數據區,要求:
(1)允許多個讀者同時執行讀操作;
(2)不允許讀者、寫者同時操作;

(3)不允許多個寫者同時操作。一次只能一個寫者  

實現原理:使用Semapore 信號量 分別表示讀者和寫者的信號量 讀者可以多個同時讀,寫者只能有一個可以寫,使用AtomicInteger定義 readerCount 和writerCount 表示當前讀者和當前寫者的數量 

package test;

import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ThreadSync {

	private static ThreadSync thrdsync;
	private static Thread t1, t2, t3, t4, t5;
	private static final Random rand = new Random();
	private static Semaphore sm = new Semaphore(2);// 信號量 允許2個線程 true表示先進先出
	private static Semaphore wsm = new Semaphore(1);// 信號量 允許1個線程
	String text = "Beginning of the Book";// 代表書本
	AtomicInteger readerCount = new AtomicInteger(0); // 記錄當前讀者數量
	AtomicInteger writerCount = new AtomicInteger(0); // 記錄當前寫者數量

	// 隨機休眠一定時間
	private void busy() {
		try {
			Thread.sleep(rand.nextInt(1000) + 1000);
		} catch (InterruptedException e) {
		}
	}

	// 寫函數
	void write(String sentence) {
		System.out.println(Thread.currentThread().getName()
				+ " started to WRITE");
		text += "\n" + sentence;
		System.out.println(text);
		System.out.println("End of Book\n");
		System.out.println(Thread.currentThread().getName()
				+ " finished WRITING");
	}

	// 讀函數
	void read() {

		System.out.println("\n" + Thread.currentThread().getName()
				+ " started to READ");
		// System.out.println(text);
		// System.out.println("End of Book\n");

	}

	// 寫者
	private class Writer implements Runnable {

		ThreadSync ts;

		Writer(ThreadSync ts) {
			super();
			this.ts = ts;

		}

		public void run() {
			while (true) {
				if (readerCount.get() == 0) { // 當沒有讀者時才 可以寫
					try {
						//System.out.println("write---readerCount= "+readerCount.get());
						//System.out.println("write---writerCount= "+writerCount.get());
						wsm.acquire(); // 信號量獲取允許
						writerCount.getAndIncrement();
					} catch (InterruptedException ex) {
						Logger.getLogger(ThreadSync.class.getName()).log(
								Level.SEVERE, null, ex);
					}
					String new_sentence = new String("\tnew line in Book");
					busy();
					ts.write(new_sentence);
					wsm.release(); // 信號量釋放
					writerCount.getAndDecrement();

					busy();

				}
			} // of while
		}
	}

	// 讀者
	private class Reader implements Runnable {

		ThreadSync ts;

		Reader(ThreadSync ts) {
			super();
			this.ts = ts;

		}

		public void run() {
			while (true) {
				if (writerCount.get() == 0) { // 沒有寫者時 纔可以讀
					try {
						//System.out.println("Read---readerCount= "+readerCount.get());
						//System.out.println("Read---writerCount= "+writerCount.get());
						sm.acquire(); // 讀者獲取允許
						readerCount.getAndIncrement();
					} catch (InterruptedException ex) {
						Logger.getLogger(ThreadSync.class.getName()).log(
								Level.SEVERE, null, ex);
					}
					// System.out.print(t);

					ts.read();
					busy();
					System.out.println(Thread.currentThread().getName()
							+ " end of read");
					sm.release(); // 釋放允許
					readerCount.getAndDecrement();
					busy();
				}
			} // of while
		}
	}

	// 創建兩個讀者 一個寫者
	public void startThreads() {
		ThreadSync ts = new ThreadSync();
		t1 = new Thread(new Writer(ts), "Writer # 1");
		t2 = new Thread(new Writer(ts), "Writer # 2");
		t3 = new Thread(new Reader(ts), "Reader # 1");
		t4 = new Thread(new Reader(ts), "Reader # 2");
		// t5 = new Thread(new Reader(ts), "Reader # 3");
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		// t5.start();
	}

	public static void main(String[] args) {
		thrdsync = new ThreadSync();
		System.out.println("Lets begin...\n");
		thrdsync.startThreads();
	}
}

輸出結果:

Lets begin...


Writer # 1 started to WRITE
Beginning of the Book
new line in Book
End of Book


Writer # 1 finished WRITING


Reader # 1 started to READ
Writer # 2 started to WRITE
Beginning of the Book
new line in Book
new line in Book
End of Book


Writer # 2 finished WRITING


Reader # 2 started to READ
Reader # 1 end of read
Reader # 2 end of read
Writer # 2 started to WRITE
Beginning of the Book
new line in Book
new line in Book
new line in Book
End of Book


Writer # 2 finished WRITING
Writer # 1 started to WRITE
Beginning of the Book
new line in Book
new line in Book
new line in Book
new line in Book
End of Book


Writer # 1 finished WRITING


Reader # 1 started to READ


Reader # 2 started to READ
Reader # 1 end of read
Reader # 2 end of read


上面的輸出結果 出現一個問題.讀者在讀的過程中寫者開始寫 .其實是由於調用 輸出函數後產生的. 希望有哪位大神可以幫忙改改,讓代碼變得更好 

發佈了34 篇原創文章 · 獲贊 45 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章