英文:
Sequential writing and reading (two threads)
问题
<b>该话题在这里继续:</b>
https://codereview.stackexchange.com/q/249978/231182
我对Java编程语言很陌生。<br>
任务:创建实现*Runnable*接口的*SequentalWriter*和*SequentalReader*类。它们必须提供一系列的写入-读取操作(即,写入-读取-写入-读取-写入-读取,等等)。<br>
我想知道这个实现是否正确,或者是否需要进行更改?
此外,欢迎指出一些小错误和bug。
import java.lang.Thread;
import vectors.Array; /* 我的数组实现 */
import vectors.CircularLinkedList; /* 我的链表实现 */
import vectors.IVector; /* Array和CircularLinkedList实现的接口 */
public class Task7Part2 {
volatile int a = 0;
public static void main(String[] args) {
IVector arr1 = new Array(2);
System.out.print("[测试] arr1: "); arr1.print();
Keeper keeperArr1 = new Keeper(arr1);
SequentalWriter seqWriter = new SequentalWriter(keeperArr1);
SequentalReader seqReader = new SequentalReader(keeperArr1);
(new Thread(seqWriter)).start();
(new Thread(seqReader)).start();
// 延迟
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
IVector arr2 = new Array(3);
System.out.print("[测试] arr2: "); arr2.print();
Keeper keeperArr2 = new Keeper(arr2);
seqWriter = new SequentalWriter(keeperArr2);
seqReader = new SequentalReader(keeperArr2);
(new Thread(seqWriter)).start();
(new Thread(seqReader)).start();
// 延迟
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
IVector list = new CircularLinkedList(4);
System.out.print("[测试] list: "); list.print();
Keeper keeperList = new Keeper(list);
seqWriter = new SequentalWriter(keeperList);
seqReader = new SequentalReader(keeperList);
(new Thread(seqWriter)).start();
(new Thread(seqReader)).start();
}
public static class Keeper {
public volatile IVector vector;
public volatile boolean isWrite;
public Keeper(IVector vector) {
this.vector = vector;
this.isWrite = true;
}
}
public static class SequentalWriter implements Runnable {
public SequentalWriter(Keeper keeper) {
this.keeper = keeper;
}
public void run() {
try {
for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
double d = Math.random();
synchronized(keeper) {
while (!keeper.isWrite) {
keeper.wait();
}
keeper.vector.set(i, d);
System.out.println("写入:" + d + " 到位置 " + i);
keeper.isWrite = false;
keeper.notify();
}
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
private Keeper keeper;
}
public static class SequentalReader implements Runnable {
public SequentalReader(Keeper keeper) {
this.keeper = keeper;
}
public void run() {
try {
for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
synchronized(keeper) {
while (keeper.isWrite) {
keeper.wait();
}
System.out.println("读取:" + keeper.vector.get(i) + " 从位置 " + i);
keeper.isWrite = true;
keeper.notify();
}
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
private Keeper keeper;
}
}
期望行为(当前看起来正常工作,但我不确定以后是否会一直如此):
[测试] arr1: 0.0 0.0
写入:0.11832270210075957 到位置 0
读取:0.11832270210075957 从位置 0
写入:0.18019604451043925 到位置 1
读取:0.18019604451043925 从位置 1
[测试] arr2: 0.0 0.0 0.0
写入:0.9208224707735939 到位置 0
读取:0.9208224707735939 从位置 0
写入:0.5204299894796229 到位置 1
读取:0.5204299894796229 从位置 1
写入:0.6221915557485913 到位置 2
读取:0.6221915557485913 从位置 2
[测试] list: 0.0 0.0 0.0 0.0
写入:0.2718292615666258 到位置 0
读取:0.2718292615666258 从位置 0
写入:0.5589338156490498 到位置 1
读取:0.5589338156490498 从位置 1
写入:0.11919746734454817 到位置 2
读取:0.11919746734454817 从位置 2
写入:0.7266106446478366 到位置 3
读取:0.7266106446478366 从位置 3
英文:
<b>The topic was continued here:</b>
https://codereview.stackexchange.com/q/249978/231182
I am new to the Java programming language.<br>
Task: Create SequentalWriter and SequentalReader classes that implement the Runnable interface. They must provide a sequence of write-read operations (i.e., write-read-write-read-write-read, etc.).<br>
I would like to know if this implementation is correct or something needs to be changed?
Besides, minor bugs and errors are also welcome.
import java.lang.Thread;
import vectors.Array; /* My array implementation */
import vectors.CircularLinkedList; /* My list implementation */
import vectors.IVector; /* The interface that Array and CircularLinkedList implement */
public class Task7Part2 {
volatile int a = 0;
public static void main(String[] args) {
IVector arr1 = new Array(2);
System.out.print("[Test] arr1: "); arr1.print();
Keeper keeperArr1 = new Keeper(arr1);
SequentalWriter seqWriter = new SequentalWriter(keeperArr1);
SequentalReader seqReader = new SequentalReader(keeperArr1);
(new Thread(seqWriter)).start();
(new Thread(seqReader)).start();
// Задержка
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
IVector arr2 = new Array(3);
System.out.print("[Test] arr2: "); arr2.print();
Keeper keeperArr2 = new Keeper(arr2);
seqWriter = new SequentalWriter(keeperArr2);
seqReader = new SequentalReader(keeperArr2);
(new Thread(seqWriter)).start();
(new Thread(seqReader)).start();
// Задержка
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
IVector list = new CircularLinkedList(4);
System.out.print("[Test] list: "); list.print();
Keeper keeperList = new Keeper(list);
seqWriter = new SequentalWriter(keeperList);
seqReader = new SequentalReader(keeperList);
(new Thread(seqWriter)).start();
(new Thread(seqReader)).start();
}
public static class Keeper {
public volatile IVector vector;
public volatile boolean isWrite;
public Keeper(IVector vector) {
this.vector = vector;
this.isWrite = true;
}
}
public static class SequentalWriter implements Runnable {
public SequentalWriter(Keeper keeper) {
this.keeper = keeper;
}
public void run() {
try {
for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
double d = Math.random();
synchronized(keeper) {
while (!keeper.isWrite) {
keeper.wait();
}
keeper.vector.set(i, d);
System.out.println("Write: " + d + " to position " + i);
keeper.isWrite = false;
keeper.notify();
}
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
private Keeper keeper;
}
public static class SequentalReader implements Runnable {
public SequentalReader(Keeper keeper) {
this.keeper = keeper;
}
public void run() {
try {
for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
synchronized(keeper) {
while (keeper.isWrite) {
keeper.wait();
}
System.out.println("Read: " + keeper.vector.get(i) + " from position " + i);
keeper.isWrite = true;
keeper.notify();
}
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
private Keeper keeper;
}
}
Expected behavior (What seems to work right now, but I'm not sure it will always be that way.):
[Test] arr1: 0.0 0.0
Write: 0.11832270210075957 to position 0
Read: 0.11832270210075957 from position 0
Write: 0.18019604451043925 to position 1
Read: 0.18019604451043925 from position 1
[Test] arr2: 0.0 0.0 0.0
Write: 0.9208224707735939 to position 0
Read: 0.9208224707735939 from position 0
Write: 0.5204299894796229 to position 1
Read: 0.5204299894796229 from position 1
Write: 0.6221915557485913 to position 2
Read: 0.6221915557485913 from position 2
[Test] list: 0.0 0.0 0.0 0.0
Write: 0.2718292615666258 to position 0
Read: 0.2718292615666258 from position 0
Write: 0.5589338156490498 to position 1
Read: 0.5589338156490498 from position 1
Write: 0.11919746734454817 to position 2
Read: 0.11919746734454817 from position 2
Write: 0.7266106446478366 to position 3
Read: 0.7266106446478366 from position 3
答案1
得分: 1
经典的方法是使用信号量(Semaphores):
import java.lang.Thread;
import java.util.concurrent.Semaphore;
public class Task7Part2 {
public static void main(String[] args) throws InterruptedException {
IVector arr1 = new IVector(2);
System.out.print("[Test] arr1: ");
arr1.print();
Keeper keeperArr1 = new Keeper(arr1);
SequentalWriter seqWriter = new SequentalWriter(keeperArr1);
SequentalReader seqReader = new SequentalReader(keeperArr1);
Thread thread1 = new Thread(seqWriter);
thread1.start();
Thread thread2 = new Thread(seqReader);
thread2.start();
thread1.join();
thread2.join();
}
public static class Keeper {
public IVector vector;
public Semaphore allowWrite = new Semaphore(1);
public Semaphore allowRead = new Semaphore(0);
public Keeper(IVector vector) {
this.vector = vector;
}
public Double get(int i) throws InterruptedException {
allowRead.acquire();
Double res = vector.get(i);
allowWrite.release();
return res;
}
public void set(int i, double d) throws InterruptedException {
allowWrite.acquire();
vector.set(i, d);
allowRead.release();
}
}
public static class SequentalWriter implements Runnable {
private Keeper keeper;
public SequentalWriter(Keeper keeper) {
this.keeper = keeper;
}
public void run() {
try {
for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
double d = Math.random();
keeper.set(i, d);
System.out.println("Write: " + d + " to position " + i);
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
public static class SequentalReader implements Runnable {
private Keeper keeper;
public SequentalReader(Keeper keeper) {
this.keeper = keeper;
}
public void run() {
try {
for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
System.out.println("Read: " + keeper.get(i) + " from position " + i);
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}
英文:
the classic approach is to use Semaphores:
import java.lang.Thread;
import java.util.concurrent.Semaphore;
public class Task7Part2 {
public static void main(String[] args) throws InterruptedException {
IVector arr1 = new IVector(2);
System.out.print("[Test] arr1: "); arr1.print();
Keeper keeperArr1 = new Keeper(arr1);
SequentalWriter seqWriter = new SequentalWriter(keeperArr1);
SequentalReader seqReader = new SequentalReader(keeperArr1);
Thread thread1 = new Thread(seqWriter);
thread1.start();
Thread thread2 = new Thread(seqReader);
thread2.start();
thread1.join();
thread2.join();
}
public static class Keeper {
public IVector vector;
public Semaphore allowWrite=new Semaphore(1);
public Semaphore allowRead=new Semaphore(0);
public Keeper(IVector vector) {
this.vector = vector;
}
public Double get(int i) throws InterruptedException {
allowRead.acquire();
Double res = vector.get(i);
allowWrite.release();
return res;
}
public void set(int i, double d) throws InterruptedException {
allowWrite.acquire();
vector.set(i,d);
allowRead.release();
}
}
public static class SequentalWriter implements Runnable {
private Keeper keeper;
public SequentalWriter(Keeper keeper) {
this.keeper = keeper;
}
public void run() {
try {
for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
double d = Math.random();
keeper.set(i, d);
System.out.println("Write: " + d + " to position " + i);
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
public static class SequentalReader implements Runnable {
private Keeper keeper;
public SequentalReader(Keeper keeper) {
this.keeper = keeper;
}
public void run() {
try {
for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
System.out.println("Read: " + keeper.get(i) + " from position " + i);
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论