显示在java中与两个线程同步的用法

5lhxktic  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(334)

我一直在看多线程教程和那些关于同步的特定教程,但是我还没有实现我需要的东西。
这是一个在我的程序中同步发生的展示。
基本上,我有一个类从另一个类继承了一些函数,这些函数需要同步,以便两个线程不会同时修改一个对象(没有数据损坏)。
我以前实现的代码没有synchronize关键字,所以我可以设法看到数据损坏的发生。

  1. EditOptionsMethods e1;
  2. int threadNo;
  3. public EditOptions() {
  4. e1 = new BuildAuto();
  5. run();
  6. }
  7. public void run() {
  8. System.out.println("Thread running.");
  9. switch (threadNo) {
  10. case 0:
  11. break;
  12. case 1:
  13. break;
  14. }
  15. }
  16. public void setOptions(String optSetName1, String desiredOption1, String optSetName2, String desiredOption2) {
  17. e1.s_Option(optSetName1, desiredOption1); //
  18. e1.s_Option(optSetName2, desiredOption2);
  19. }

必须同步s\u选项,这样两个线程都不会出现。我首先将它不同步,然后我可以初始化一个循环(高索引量,假设1000,然后我与第一个线程相加,与第二个线程相减),以查看发生的损坏作为一个例子。
但我找不到一个方法来表达这个。
如果有人知道我如何实现这个,那就太棒了。

2ledvvac

2ledvvac1#

首先创建一个将容纳线程的结构:

  1. List<Thread> threads = new ArrayList<>();

然后初始化它,并将工作分配给线程:

  1. int total_threads = 2;
  2. for(int i = 0; i < total_threads; i++){
  3. Thread thread = new Thread(() -> {
  4. // the work to be done by the threads
  5. });
  6. threads.add(thread);
  7. }

运行线程:

  1. threads.forEach(Thread::start);

最后,等待线程完成其工作:

  1. threads.forEach(t -> {
  2. try {
  3. t.join();
  4. } catch (InterruptedException e) {
  5. e.printStackTrace();
  6. }
  7. });

通过一个运行示例:

  1. import java.util.*;
  2. public class SomeClass {
  3. private int x;
  4. public void addX(int y){ x = x + y;}
  5. public static void main(String[] args) {
  6. SomeClass example = new SomeClass();
  7. List<Thread> threads = new ArrayList<>();
  8. int total_threads = 2;
  9. for(int i = 1; i < total_threads + 1; i++){
  10. final int threadID = i;
  11. Thread thread = new Thread(() -> {
  12. for(int j = 0; j < 1000; j++ )
  13. example.addX((threadID % 2 == 0) ? -threadID : threadID);
  14. });
  15. threads.add(thread);
  16. }
  17. threads.forEach(Thread::start);
  18. threads.forEach(t -> {
  19. try {
  20. t.join();
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. });
  25. System.out.println(example.x);
  26. }
  27. }

现在尝试运行上面的示例,并同步线程完成的工作:

  1. Thread thread = new Thread(() -> {
  2. for(int j = 0; j < 1000; j++ )
  3. example.addX((threadID % 2 == 0) ? -threadID : threadID);
  4. });

与:

  1. Thread thread = new Thread(() -> {
  2. synchronized(example){ // <-- adding synchronization
  3. for(int j = 0; j < 1000; j++ )
  4. example.addX((threadID % 2 == 0) ? -threadID : threadID);
  5. }
  6. });

对于使用同步的版本,您可以根据需要多次运行代码,输出将始终保持同步 -1000 (使用2个螺纹)。然而,对于没有同步的版本,由于变量更新期间发生的竞争条件,输出将是不确定的 x .
而不是使用 Thread 直接初始化,您可以选择更高的抽象,即执行器:

  1. public class SomeClass2 {
  2. private int x;
  3. public void addX(int y){x = x + y;}
  4. public static void main(String[] args) {
  5. SomeClass2 example = new SomeClass2();
  6. int total_threads = 2;
  7. ExecutorService pool = Executors.newFixedThreadPool(total_threads);
  8. pool.execute(() -> {
  9. synchronized (example) {
  10. parallel_task(example, -2);
  11. }
  12. });
  13. pool.execute(() -> {
  14. synchronized (example) {
  15. parallel_task(example, 1);
  16. }
  17. });
  18. pool.shutdown();
  19. try { pool.awaitTermination(1, TimeUnit.MINUTES);}
  20. catch (InterruptedException e) {e.printStackTrace();}
  21. System.out.println(example.x);
  22. }
  23. private static void parallel_task(SomeClass2 example, int i) {
  24. thread_sleep();
  25. for (int j = 0; j < 1000; j++)
  26. example.addX(i);
  27. }
  28. private static void thread_sleep() {
  29. try { Thread.sleep(1000); }
  30. catch (InterruptedException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. }

我添加了 thread_sleep() 以确保两个并行任务不会被同一线程从线程池中拾取。

展开查看全部

相关问题