gpt4 book ai didi

java - 显示 Java 中与 2 个线程同步的用法

转载 作者:行者123 更新时间:2023-12-03 11:18:54 29 4
gpt4 key购买 nike

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

 EditOptionsMethods e1;
int threadNo;

public EditOptions() {
e1 = new BuildAuto();
run();
}

public void run() {
System.out.println("Thread running.");

switch (threadNo) {
case 0:

break;

case 1:
break;
}

}

public void setOptions(String optSetName1, String desiredOption1, String optSetName2, String desiredOption2) {
e1.s_Option(optSetName1, desiredOption1); //
e1.s_Option(optSetName2, desiredOption2);
}
s_Option 必须同步,因此两个线程都不会发生。
我首先将在没有同步的情况下使用它,然后我可以初始化一个循环(具有高索引量,假设为 1000,然后我用第一个线程添加,然后用第二个线程减去)以查看发生的损坏作为示例。
但我没有找到一种方式来展示这一点。
如果有人知道我如何实现这一点,那就太棒了。

最佳答案

首先创建一个结构来保存线程:

   List<Thread> threads = new ArrayList<>();
然后初始化它,并将工作分配给线程:
   int total_threads = 2;
for(int i = 0; i < total_threads; i++){
Thread thread = new Thread(() -> {
// the work to be done by the threads
});
threads.add(thread);
}
运行线程:
threads.forEach(Thread::start);
最后,等待线程完成它们的工作:
   threads.forEach(t -> {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
用一个运行的例子:
import java.util.*;

public class SomeClass {

private int x;

public void addX(int y){ x = x + y;}


public static void main(String[] args) {
SomeClass example = new SomeClass();
List<Thread> threads = new ArrayList<>();
int total_threads = 2;
for(int i = 1; i < total_threads + 1; i++){
final int threadID = i;
Thread thread = new Thread(() -> {
for(int j = 0; j < 1000; j++ )
example.addX((threadID % 2 == 0) ? -threadID : threadID);
});
threads.add(thread);
}
threads.forEach(Thread::start);
threads.forEach(t -> {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println(example.x);
}
}
现在尝试在同步和不同步线程完成的工作的情况下运行上面的示例:
   Thread thread  = new Thread(() -> {
for(int j = 0; j < 1000; j++ )
example.addX((threadID % 2 == 0) ? -threadID : threadID);
});
相对:
 Thread thread  = new Thread(() -> {
synchronized(example){ // <-- adding synchronization
for(int j = 0; j < 1000; j++ )
example.addX((threadID % 2 == 0) ? -threadID : threadID);
}
});
对于使用同步的版本,您可以根据需要多次运行代码,输出将始终为 -1000 (使用 2 个线程)。但是,对于没有同步的版本,由于在更新变量 x 期间发生竞争条件,输出将是不确定的。 .
而不是使用 Thread直接类,你可以选择更高的抽象,即 executors :
public class SomeClass2 {

private int x;

public void addX(int y){x = x + y;}

public static void main(String[] args) {
SomeClass2 example = new SomeClass2();
int total_threads = 2;
ExecutorService pool = Executors.newFixedThreadPool(total_threads);
pool.execute(() -> {
synchronized (example) {
parallel_task(example, -2);
}
});
pool.execute(() -> {
synchronized (example) {
parallel_task(example, 1);
}
});

pool.shutdown();
try { pool.awaitTermination(1, TimeUnit.MINUTES);}
catch (InterruptedException e) {e.printStackTrace();}
System.out.println(example.x);
}

private static void parallel_task(SomeClass2 example, int i) {
thread_sleep();
for (int j = 0; j < 1000; j++)
example.addX(i);
}

private static void thread_sleep() {
try { Thread.sleep(1000); }
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
我添加了 thread_sleep()确保两个并行任务不会被线程池中的同一个线程占用。

关于java - 显示 Java 中与 2 个线程同步的用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65166368/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com