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

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

Sequential writing and reading (two threads)

问题

  1. <b>该话题在这里继续</b>
  2. https://codereview.stackexchange.com/q/249978/231182
  3. 我对Java编程语言很陌生<br>
  4. 任务创建实现*Runnable*接口的*SequentalWriter**SequentalReader*它们必须提供一系列的写入-读取操作写入-读取-写入-读取-写入-读取等等)。<br>
  5. 我想知道这个实现是否正确或者是否需要进行更改
  6. 此外欢迎指出一些小错误和bug
  1. import java.lang.Thread;
  2. import vectors.Array; /* 我的数组实现 */
  3. import vectors.CircularLinkedList; /* 我的链表实现 */
  4. import vectors.IVector; /* Array和CircularLinkedList实现的接口 */
  5. public class Task7Part2 {
  6. volatile int a = 0;
  7. public static void main(String[] args) {
  8. IVector arr1 = new Array(2);
  9. System.out.print("[测试] arr1: "); arr1.print();
  10. Keeper keeperArr1 = new Keeper(arr1);
  11. SequentalWriter seqWriter = new SequentalWriter(keeperArr1);
  12. SequentalReader seqReader = new SequentalReader(keeperArr1);
  13. (new Thread(seqWriter)).start();
  14. (new Thread(seqReader)).start();
  15. // 延迟
  16. try {
  17. Thread.sleep(100);
  18. } catch (InterruptedException e) {
  19. System.out.println(e.getMessage());
  20. }
  21. IVector arr2 = new Array(3);
  22. System.out.print("[测试] arr2: "); arr2.print();
  23. Keeper keeperArr2 = new Keeper(arr2);
  24. seqWriter = new SequentalWriter(keeperArr2);
  25. seqReader = new SequentalReader(keeperArr2);
  26. (new Thread(seqWriter)).start();
  27. (new Thread(seqReader)).start();
  28. // 延迟
  29. try {
  30. Thread.sleep(100);
  31. } catch (InterruptedException e) {
  32. System.out.println(e.getMessage());
  33. }
  34. IVector list = new CircularLinkedList(4);
  35. System.out.print("[测试] list: "); list.print();
  36. Keeper keeperList = new Keeper(list);
  37. seqWriter = new SequentalWriter(keeperList);
  38. seqReader = new SequentalReader(keeperList);
  39. (new Thread(seqWriter)).start();
  40. (new Thread(seqReader)).start();
  41. }
  42. public static class Keeper {
  43. public volatile IVector vector;
  44. public volatile boolean isWrite;
  45. public Keeper(IVector vector) {
  46. this.vector = vector;
  47. this.isWrite = true;
  48. }
  49. }
  50. public static class SequentalWriter implements Runnable {
  51. public SequentalWriter(Keeper keeper) {
  52. this.keeper = keeper;
  53. }
  54. public void run() {
  55. try {
  56. for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
  57. double d = Math.random();
  58. synchronized(keeper) {
  59. while (!keeper.isWrite) {
  60. keeper.wait();
  61. }
  62. keeper.vector.set(i, d);
  63. System.out.println("写入:" + d + " 到位置 " + i);
  64. keeper.isWrite = false;
  65. keeper.notify();
  66. }
  67. }
  68. } catch (Exception e) {
  69. System.out.println(e.toString());
  70. }
  71. }
  72. private Keeper keeper;
  73. }
  74. public static class SequentalReader implements Runnable {
  75. public SequentalReader(Keeper keeper) {
  76. this.keeper = keeper;
  77. }
  78. public void run() {
  79. try {
  80. for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
  81. synchronized(keeper) {
  82. while (keeper.isWrite) {
  83. keeper.wait();
  84. }
  85. System.out.println("读取:" + keeper.vector.get(i) + " 从位置 " + i);
  86. keeper.isWrite = true;
  87. keeper.notify();
  88. }
  89. }
  90. } catch (Exception e) {
  91. System.out.println(e.toString());
  92. }
  93. }
  94. private Keeper keeper;
  95. }
  96. }
  1. 期望行为当前看起来正常工作但我不确定以后是否会一直如此):
  1. [测试] arr1: 0.0 0.0
  2. 写入0.11832270210075957 到位置 0
  3. 读取0.11832270210075957 从位置 0
  4. 写入0.18019604451043925 到位置 1
  5. 读取0.18019604451043925 从位置 1
  6. [测试] arr2: 0.0 0.0 0.0
  7. 写入0.9208224707735939 到位置 0
  8. 读取0.9208224707735939 从位置 0
  9. 写入0.5204299894796229 到位置 1
  10. 读取0.5204299894796229 从位置 1
  11. 写入0.6221915557485913 到位置 2
  12. 读取0.6221915557485913 从位置 2
  13. [测试] list: 0.0 0.0 0.0 0.0
  14. 写入0.2718292615666258 到位置 0
  15. 读取0.2718292615666258 从位置 0
  16. 写入0.5589338156490498 到位置 1
  17. 读取0.5589338156490498 从位置 1
  18. 写入0.11919746734454817 到位置 2
  19. 读取0.11919746734454817 从位置 2
  20. 写入0.7266106446478366 到位置 3
  21. 读取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.

  1. import java.lang.Thread;
  2. import vectors.Array; /* My array implementation */
  3. import vectors.CircularLinkedList; /* My list implementation */
  4. import vectors.IVector; /* The interface that Array and CircularLinkedList implement */
  5. public class Task7Part2 {
  6. volatile int a = 0;
  7. public static void main(String[] args) {
  8. IVector arr1 = new Array(2);
  9. System.out.print(&quot;[Test] arr1: &quot;); arr1.print();
  10. Keeper keeperArr1 = new Keeper(arr1);
  11. SequentalWriter seqWriter = new SequentalWriter(keeperArr1);
  12. SequentalReader seqReader = new SequentalReader(keeperArr1);
  13. (new Thread(seqWriter)).start();
  14. (new Thread(seqReader)).start();
  15. // Задержка
  16. try {
  17. Thread.sleep(100);
  18. } catch (InterruptedException e) {
  19. System.out.println(e.getMessage());
  20. }
  21. IVector arr2 = new Array(3);
  22. System.out.print(&quot;[Test] arr2: &quot;); arr2.print();
  23. Keeper keeperArr2 = new Keeper(arr2);
  24. seqWriter = new SequentalWriter(keeperArr2);
  25. seqReader = new SequentalReader(keeperArr2);
  26. (new Thread(seqWriter)).start();
  27. (new Thread(seqReader)).start();
  28. // Задержка
  29. try {
  30. Thread.sleep(100);
  31. } catch (InterruptedException e) {
  32. System.out.println(e.getMessage());
  33. }
  34. IVector list = new CircularLinkedList(4);
  35. System.out.print(&quot;[Test] list: &quot;); list.print();
  36. Keeper keeperList = new Keeper(list);
  37. seqWriter = new SequentalWriter(keeperList);
  38. seqReader = new SequentalReader(keeperList);
  39. (new Thread(seqWriter)).start();
  40. (new Thread(seqReader)).start();
  41. }
  42. public static class Keeper {
  43. public volatile IVector vector;
  44. public volatile boolean isWrite;
  45. public Keeper(IVector vector) {
  46. this.vector = vector;
  47. this.isWrite = true;
  48. }
  49. }
  50. public static class SequentalWriter implements Runnable {
  51. public SequentalWriter(Keeper keeper) {
  52. this.keeper = keeper;
  53. }
  54. public void run() {
  55. try {
  56. for (int i = 0, size = keeper.vector.size(); i &lt; size; ++i) {
  57. double d = Math.random();
  58. synchronized(keeper) {
  59. while (!keeper.isWrite) {
  60. keeper.wait();
  61. }
  62. keeper.vector.set(i, d);
  63. System.out.println(&quot;Write: &quot; + d + &quot; to position &quot; + i);
  64. keeper.isWrite = false;
  65. keeper.notify();
  66. }
  67. }
  68. } catch (Exception e) {
  69. System.out.println(e.toString());
  70. }
  71. }
  72. private Keeper keeper;
  73. }
  74. public static class SequentalReader implements Runnable {
  75. public SequentalReader(Keeper keeper) {
  76. this.keeper = keeper;
  77. }
  78. public void run() {
  79. try {
  80. for (int i = 0, size = keeper.vector.size(); i &lt; size; ++i) {
  81. synchronized(keeper) {
  82. while (keeper.isWrite) {
  83. keeper.wait();
  84. }
  85. System.out.println(&quot;Read: &quot; + keeper.vector.get(i) + &quot; from position &quot; + i);
  86. keeper.isWrite = true;
  87. keeper.notify();
  88. }
  89. }
  90. } catch (Exception e) {
  91. System.out.println(e.toString());
  92. }
  93. }
  94. private Keeper keeper;
  95. }
  96. }

Expected behavior (What seems to work right now, but I'm not sure it will always be that way.):

  1. [Test] arr1: 0.0 0.0
  2. Write: 0.11832270210075957 to position 0
  3. Read: 0.11832270210075957 from position 0
  4. Write: 0.18019604451043925 to position 1
  5. Read: 0.18019604451043925 from position 1
  6. [Test] arr2: 0.0 0.0 0.0
  7. Write: 0.9208224707735939 to position 0
  8. Read: 0.9208224707735939 from position 0
  9. Write: 0.5204299894796229 to position 1
  10. Read: 0.5204299894796229 from position 1
  11. Write: 0.6221915557485913 to position 2
  12. Read: 0.6221915557485913 from position 2
  13. [Test] list: 0.0 0.0 0.0 0.0
  14. Write: 0.2718292615666258 to position 0
  15. Read: 0.2718292615666258 from position 0
  16. Write: 0.5589338156490498 to position 1
  17. Read: 0.5589338156490498 from position 1
  18. Write: 0.11919746734454817 to position 2
  19. Read: 0.11919746734454817 from position 2
  20. Write: 0.7266106446478366 to position 3
  21. Read: 0.7266106446478366 from position 3

答案1

得分: 1

经典的方法是使用信号量(Semaphores):

  1. import java.lang.Thread;
  2. import java.util.concurrent.Semaphore;
  3. public class Task7Part2 {
  4. public static void main(String[] args) throws InterruptedException {
  5. IVector arr1 = new IVector(2);
  6. System.out.print("[Test] arr1: ");
  7. arr1.print();
  8. Keeper keeperArr1 = new Keeper(arr1);
  9. SequentalWriter seqWriter = new SequentalWriter(keeperArr1);
  10. SequentalReader seqReader = new SequentalReader(keeperArr1);
  11. Thread thread1 = new Thread(seqWriter);
  12. thread1.start();
  13. Thread thread2 = new Thread(seqReader);
  14. thread2.start();
  15. thread1.join();
  16. thread2.join();
  17. }
  18. public static class Keeper {
  19. public IVector vector;
  20. public Semaphore allowWrite = new Semaphore(1);
  21. public Semaphore allowRead = new Semaphore(0);
  22. public Keeper(IVector vector) {
  23. this.vector = vector;
  24. }
  25. public Double get(int i) throws InterruptedException {
  26. allowRead.acquire();
  27. Double res = vector.get(i);
  28. allowWrite.release();
  29. return res;
  30. }
  31. public void set(int i, double d) throws InterruptedException {
  32. allowWrite.acquire();
  33. vector.set(i, d);
  34. allowRead.release();
  35. }
  36. }
  37. public static class SequentalWriter implements Runnable {
  38. private Keeper keeper;
  39. public SequentalWriter(Keeper keeper) {
  40. this.keeper = keeper;
  41. }
  42. public void run() {
  43. try {
  44. for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
  45. double d = Math.random();
  46. keeper.set(i, d);
  47. System.out.println("Write: " + d + " to position " + i);
  48. }
  49. } catch (Exception e) {
  50. System.out.println(e.toString());
  51. }
  52. }
  53. }
  54. public static class SequentalReader implements Runnable {
  55. private Keeper keeper;
  56. public SequentalReader(Keeper keeper) {
  57. this.keeper = keeper;
  58. }
  59. public void run() {
  60. try {
  61. for (int i = 0, size = keeper.vector.size(); i < size; ++i) {
  62. System.out.println("Read: " + keeper.get(i) + " from position " + i);
  63. }
  64. } catch (Exception e) {
  65. System.out.println(e.toString());
  66. }
  67. }
  68. }
  69. }
英文:

the classic approach is to use Semaphores:

  1. import java.lang.Thread;
  2. import java.util.concurrent.Semaphore;
  3. public class Task7Part2 {
  4. public static void main(String[] args) throws InterruptedException {
  5. IVector arr1 = new IVector(2);
  6. System.out.print(&quot;[Test] arr1: &quot;); arr1.print();
  7. Keeper keeperArr1 = new Keeper(arr1);
  8. SequentalWriter seqWriter = new SequentalWriter(keeperArr1);
  9. SequentalReader seqReader = new SequentalReader(keeperArr1);
  10. Thread thread1 = new Thread(seqWriter);
  11. thread1.start();
  12. Thread thread2 = new Thread(seqReader);
  13. thread2.start();
  14. thread1.join();
  15. thread2.join();
  16. }
  17. public static class Keeper {
  18. public IVector vector;
  19. public Semaphore allowWrite=new Semaphore(1);
  20. public Semaphore allowRead=new Semaphore(0);
  21. public Keeper(IVector vector) {
  22. this.vector = vector;
  23. }
  24. public Double get(int i) throws InterruptedException {
  25. allowRead.acquire();
  26. Double res = vector.get(i);
  27. allowWrite.release();
  28. return res;
  29. }
  30. public void set(int i, double d) throws InterruptedException {
  31. allowWrite.acquire();
  32. vector.set(i,d);
  33. allowRead.release();
  34. }
  35. }
  36. public static class SequentalWriter implements Runnable {
  37. private Keeper keeper;
  38. public SequentalWriter(Keeper keeper) {
  39. this.keeper = keeper;
  40. }
  41. public void run() {
  42. try {
  43. for (int i = 0, size = keeper.vector.size(); i &lt; size; ++i) {
  44. double d = Math.random();
  45. keeper.set(i, d);
  46. System.out.println(&quot;Write: &quot; + d + &quot; to position &quot; + i);
  47. }
  48. } catch (Exception e) {
  49. System.out.println(e.toString());
  50. }
  51. }
  52. }
  53. public static class SequentalReader implements Runnable {
  54. private Keeper keeper;
  55. public SequentalReader(Keeper keeper) {
  56. this.keeper = keeper;
  57. }
  58. public void run() {
  59. try {
  60. for (int i = 0, size = keeper.vector.size(); i &lt; size; ++i) {
  61. System.out.println(&quot;Read: &quot; + keeper.get(i) + &quot; from position &quot; + i);
  62. }
  63. } catch (Exception e) {
  64. System.out.println(e.toString());
  65. }
  66. }
  67. }
  68. }

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:

确定