Java 需要了解多线程环境中原子整数代码使用中的问题
在一次采访中,有人向我提出了一个编码问题,我必须找出代码中的问题,并提出适当的解决方案 请在下面找到完整的代码:Java 需要了解多线程环境中原子整数代码使用中的问题,java,atomicinteger,Java,Atomicinteger,在一次采访中,有人向我提出了一个编码问题,我必须找出代码中的问题,并提出适当的解决方案 请在下面找到完整的代码: import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class Atomic { static AtomicInteger count = ne
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Atomic {
static AtomicInteger count = new AtomicInteger(0);
static int counter = 0;
public static class Runnable extends Thread {
public void run() {
while (count.getAndSet(1) != 0) {
try {
Thread.sleep(3000);
} catch (Exception e) {
}
}
counter = counter + 1;
count.set(0);
}
}
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
Runnable runnable = new Runnable();
executor.execute(runnable);
}
executor.shutdown();
}
}
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.AtomicInteger;
公共级原子弹{
静态AtomicInteger计数=新的AtomicInteger(0);
静态整数计数器=0;
公共静态类Runnable扩展线程{
公开募捐{
while(count.getAndSet(1)!=0){
试一试{
睡眠(3000);
}捕获(例外e){
}
}
计数器=计数器+1;
计数集(0);
}
}
公共静态void main(字符串[]args){
ExecutorService executor=Executors.newFixedThreadPool(10);
对于(int i=0;i<10;i++){
Runnable Runnable=新的Runnable();
执行器。执行(可运行);
}
executor.shutdown();
}
}
这段代码运行正常。但问题是,若线程数量增加,或者若我运行For循环近10000次,这段代码就会出现一些问题
我试图找到问题,但找不到。此代码有几处错误。你没有说“有一些问题”的意思,但这里有一些跳出的东西
首先,
计数器
变量没有安全更新。多线程不能保证最后写入值的可见性;也不能保证在读写之间没有其他线程更新其值
解决这个问题的简单方法是:将计数器
更改为原子整数
,然后使用getAndIncrement
或incrementAndGet
将其递增
其次,
公共静态类Runnable扩展线程{
非常可疑
Java.lang.Runnable
)线程
,尤其是当您只需要一个java.lang.Runnable
来添加带有执行器服务的execute时
public static class MyRunnable implements Runnable {
(或者随便你怎么称呼它)
或者您可以只声明一个匿名类:
executor.execute(new Runnable() { /* body */ });
或者您可以只声明一个lambda:
executor.execute(() -> { /* body */ });
第三,
count
在这里似乎并没有起到明显的作用
- 如果“标志”为假:
- 将“flag”设置为true
- 增加一个变量
- 将“flag”设置为false
- 否则:
- 等3秒钟
- 再试一次
count
在这里扮演着“标志”的角色。它实际上只是一个AtomicBoolean
但是,如果将计数器设置为原子整数
,则根本不需要单独的计数
变量:
while (true) {
int current = counter.get();
if (counter.compareAndSet(current, current + 1)) {
// Nothing else is trying to update "current" at the same time:
// we updated it. Stop.
break;
}
// Something else is trying to update at the same time.
// Sleep for 3 seconds.
Thread.sleep(3000);
}
提示:如果两个线程试图同时递增计数器
,会发生什么情况?此代码中的一个非功能性问题是“公共静态类可运行扩展线程{
”。这是可行的,但哦,这真的不是一个好主意,至少有两种方式。