顺序写入和读取(两个线程)

huangapple go评论70阅读模式
英文:

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(&quot;[Test] arr1: &quot;); 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(&quot;[Test] arr2: &quot;); 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(&quot;[Test] list: &quot;); 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 &lt; size; ++i) {
double d = Math.random();
synchronized(keeper) {
while (!keeper.isWrite) {
keeper.wait();
}
keeper.vector.set(i, d);
System.out.println(&quot;Write: &quot; + d + &quot; to position &quot; + 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 &lt; size; ++i) {
synchronized(keeper) {
while (keeper.isWrite) {
keeper.wait();
}
System.out.println(&quot;Read: &quot; + keeper.vector.get(i) + &quot; from position &quot; + 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(&quot;[Test] arr1: &quot;); 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 &lt; size; ++i) {
double d = Math.random();
keeper.set(i, d);
System.out.println(&quot;Write: &quot; + d + &quot; to position &quot; + 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 &lt; size; ++i) {
System.out.println(&quot;Read: &quot; + keeper.get(i) + &quot; from position &quot; + i);
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}

huangapple
  • 本文由 发表于 2020年9月29日 02:45:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/64107900.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定