Java 在writer-reader中使用信号量
所以我正在参加一门多线程开发课程,目前正在学习信号量。在我们最近的任务中,我们应该使用三个线程和两个队列。writer线程将字符写入第一个队列,然后“encryptor”线程将从该队列读取字符,加密字符,然后将其添加到第二个队列。然后我们有一个从第二个队列读取的读线程。为了处理同步,我们应该使用信号量和互斥,但我没有使用任何:Java 在writer-reader中使用信号量,java,multithreading,semaphore,Java,Multithreading,Semaphore,所以我正在参加一门多线程开发课程,目前正在学习信号量。在我们最近的任务中,我们应该使用三个线程和两个队列。writer线程将字符写入第一个队列,然后“encryptor”线程将从该队列读取字符,加密字符,然后将其添加到第二个队列。然后我们有一个从第二个队列读取的读线程。为了处理同步,我们应该使用信号量和互斥,但我没有使用任何: public class Buffer { private Queue<Character> qPlain = new LinkedList<Chara
public class Buffer {
private Queue<Character> qPlain = new LinkedList<Character>();
private Queue<Character> qEncrypt = new LinkedList<Character>();
private final int CAPACITY = 3;
public Buffer() {
System.out.println("New Buffer!");
}
public synchronized void addPlain(char c) {
while (qPlain.size() == CAPACITY) {
try {
wait();
System.out.println("addPlain is waiting to add Data");
} catch (InterruptedException e) {
}
}
qPlain.add(c);
notifyAll();
System.out.println("addPlain Adding Data-" + c);
}
public synchronized char removePlain() {
while (qPlain.size() == 0) {
try {
wait();
System.out.println("----------removePlain is waiting to return Data.");
} catch (InterruptedException e) {
}
}
notifyAll();
char c = qPlain.remove();
System.out.println("---------------removePlain Returning Data-" + c);
return c;
}
public synchronized void addEncrypt(char c) {
while (qEncrypt.size() == CAPACITY) {
try {
wait();
System.out.println("addEncrypt is waiting to add Data");
} catch (InterruptedException e) {
}
}
qEncrypt.add(c);
notifyAll();
System.out.println("addEncrypt Adding Data-" + c);
}
public synchronized char removeEncrypt() {
while (qEncrypt.size() == 0) {
try {
wait();
System.out.println("----------------removeEncrypt is waiting to return Data.");
} catch (InterruptedException e) {
}
}
notifyAll();
char c = qEncrypt.remove();
System.out.println("--------------removeEncrypt Returning Data-" + c);
return c;
}
}
公共类缓冲区{
private Queue qPlain=new LinkedList();
私有队列qEncrypt=new LinkedList();
私人最终国际通行能力=3;
公共缓冲区(){
System.out.println(“新缓冲区!”);
}
公共同步void addPlain(字符c){
while(qPlain.size()=容量){
试一试{
等待();
System.out.println(“addPlain正在等待添加数据”);
}捕捉(中断异常e){
}
}
qPlain.add(c);
notifyAll();
System.out.println(“添加数据的addPlain-”+c);
}
公共同步的char removePlain(){
而(qPlain.size()=0){
试一试{
等待();
System.out.println(“------------removePlain正在等待返回数据”);
}捕捉(中断异常e){
}
}
notifyAll();
char c=qPlain.remove();
System.out.println(“--------------removePlain返回数据-”+c);
返回c;
}
公共同步作废补遗(字符c){
while(qEncrypt.size()=容量){
试一试{
等待();
System.out.println(“addEncrypt正在等待添加数据”);
}捕捉(中断异常e){
}
}
qEncrypt.添加(c);
notifyAll();
System.out.println(“添加数据的加密-”+c);
}
公共同步字符removeEncrypt(){
while(qEncrypt.size()=0){
试一试{
等待();
System.out.println(“------------removeEncrypt正在等待返回数据。”);
}捕捉(中断异常e){
}
}
notifyAll();
char c=qEncrypt.remove();
System.out.println(“--------------removeEncrypt返回数据-”+c);
返回c;
}
}
这很好,但我不会通过,因为我没有使用任何信号量。我确实理解这个概念,但我不认为在这种情况下使用任何东西有什么意义。我有两个队列,每个队列只有一个读写器
编辑:改为使用信号量更新。它几乎可以工作,当队列为空时调用removePlain()方法get时,问题就出现了。我很确定我应该阻止它,但我在这里迷路了。我可以不在这里使用互斥吗
public class Buffer {
private Semaphore encryptedSem = new Semaphore(0);
private Semaphore decryptedSem = new Semaphore(0);
private final Queue<Character> qPlain = new LinkedList<Character>();
private final Queue<Character> qEncrypt = new LinkedList<Character>();
private final int CAPACITY = 3;
private boolean startedWrite = false;
private boolean startedRead = false;
/**
* Adds a character to the queue containing non encrypted chars.
*
* @param c
*/
public void addPlain(char c) {
// Makes sure that this writer executes first.
if (!startedWrite) {
startedWrite = true;
encryptedSem = new Semaphore(1);
}
if (qPlain.size() < CAPACITY) {
aquireLock(encryptedSem);
System.out.println("addPlain has lock");
qPlain.add(c);
realeseLock(encryptedSem);
}
}
/**
* Removes and returns the next char in the non encrypted queue.
*
* @return
*/
public char removePlain() {
// TODO Need to fix what happens when the queue is 0. Right now it just
// returns a char that is 0. This needs to be blocked somehow.
char c = 0;
if (qPlain.size() > 0) {
aquireLock(encryptedSem);
System.out.println("removePlain has lock");
c = qPlain.remove();
realeseLock(encryptedSem);
} else {
System.out.println("REMOVEPLAIN CALLED WHEN qPlain IS EMPTY");
}
return c;
}
/**
* Adds a character to the queue containing the encrypted chars.
*
* @param c
*/
public void addEncrypt(char c) {
if (!startedRead) {
startedRead = true;
decryptedSem = new Semaphore(1);
}
if (qEncrypt.size() < CAPACITY) {
aquireLock(decryptedSem);
System.out.println("addEncrypt has lock");
qEncrypt.add(c);
realeseLock(decryptedSem);
}
}
/**
* Removes and returns the next char in the encrypted queue.
*
* @return
*/
public char removeEncrypt() {
char c = 0;
if (qEncrypt.size() > 0) {
aquireLock(decryptedSem);
System.out.println("removeEncrypt has lock");
c = qEncrypt.remove();
realeseLock(decryptedSem);
}
return c;
}
/**
* Aquries lock on the given semaphore.
*
* @param sem
*/
private void aquireLock(Semaphore sem) {
try {
sem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Realeses lock on the given semaphore.
*
* @param sem
*/
private void realeseLock(Semaphore sem) {
sem.release();
}
公共类缓冲区{
私有信号量encryptedSem=新信号量(0);
私有信号量decryptedSem=新信号量(0);
private final Queue qPlain=new LinkedList();
private final Queue qEncrypt=new LinkedList();
私人最终国际通行能力=3;
私有布尔startedWrite=false;
私有布尔startedRead=false;
/**
*向包含未加密字符的队列中添加字符。
*
*@param c
*/
公共空白地址(字符c){
//确保此写入程序首先执行。
如果(!startedWrite){
startedWrite=true;
encryptedSem=新信号量(1);
}
if(qPlain.size()<容量){
aquireLock(加密扫描电镜);
System.out.println(“addPlain有锁”);
qPlain.添加(c);
realeseLock(encryptedSem);
}
}
/**
*删除并返回非加密队列中的下一个字符。
*
*@返回
*/
public char removePlain(){
//TODO需要修复队列为0时发生的情况。现在它只是
//返回一个0字符。需要以某种方式阻止该字符。
字符c=0;
如果(qPlain.size()>0){
aquireLock(加密扫描电镜);
System.out.println(“removePlain有锁”);
c=qPlain.remove();
realeseLock(encryptedSem);
}否则{
System.out.println(“当qPlain为空时调用REMOVEPLAIN”);
}
返回c;
}
/**
*向包含加密字符的队列中添加字符。
*
*@param c
*/
公共作废补遗(字符c){
如果(!startedRead){
startedRead=true;
decryptedSem=新信号量(1);
}
if(qEncrypt.size()<容量){
阿奎雷洛克(解密扫描电镜);
System.out.println(“addEncrypt有锁”);
qEncrypt.添加(c);
realeseLock(decryptedSem);
}
}
/**
*删除并返回加密队列中的下一个字符。
*
*@返回
*/
公共字符删除加密(){
字符c=0;
如果(qEncrypt.size()>0){
阿奎雷洛克(解密扫描电镜);
System.out.println(“removeEncrypt有锁”);
c=qEncrypt.remove();
realeseLock(decryptedSem);
}
返回c;
}
/**
*aquiries锁定给定的信号量。
*
*@param-sem
*/
专用void aquireLock(信号量sem){
试一试{
sem.acquire();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
/**
*Realeses锁定给定的信号量。
*
*@param-sem
*/
私有void realeseLock(信号量sem){
sem.release();
}
}好的,那么试着解决你的问题,而不做家庭作业:-) 关于你的第一个样品 乍一看,这是一个工作样本。您正在通过
synchronized
关键字使用互斥形式,该关键字允许您正确使用this.wait/notify
。这还提供了确保每个线程在同一个监视器上同步的保护措施,从而在安全之前提供足够的
换句话说,多亏了这一个监视器,您可以确信synchronized
方法下的任何内容都是以独占方式执行的,并且这些方法的副作用在其他方法中是可见的
唯一的小问题是,您的队列不是最终的
,这取决于指导原则和整个系统/线程的引导方式
if (qPlain.size() > 0) {
aquireLock(encryptedSem);
...
c = qPlain.remove();
realeseLock(encryptedSem);
} else {
System.out.println("REMOVEPLAIN CALLED WHEN qPlain IS EMPTY");
}
acuquireSemaphore();
try {
// do something
} finally {
releaseSemaphore();
}