我正在尝试运行一个具有 4 个线程的程序。我想了解线程中实例变量的行为。在此我需要将一个值传递给该方法。因此,我这样做是为了传递该值并将其用于进一步处理。
@Component
class ThreadExample implements Runnable
{
String file;
public void setFile(String file)
{
this.file = file;
}
@override
public void run()
{
readFile(file);
}
public void readFile(String fileName)
{
//logic for reading file
}
}
@component
class ThreadCall
{
@Autowired
ThreadExample ex;
public void testThread()
{
ExecutorService executor2 = Executors.newFixedThreadPool(4);
getFiles()
.stream()
.forEach(f-> {
ex.setFile(f);
executor2.submit(ex);
});
}
}
getFiles()
API 返回文件名列表。我正在尝试在 Spring 中执行此操作。
这里,4个线程将同时工作。对象ex
是 Autowiring
的,因此它只会被实例化一次。
file
变量值会如何影响?
我想,一个线程将尝试通过 setFile(file)
设置文件,并且在 readFile
中使用它之前,它会被另一个线程更改。
如何解决这个问题?多线程中如何传值?
如果我将 'file' 设置为 volatile
,我的问题会得到解决吗?
最佳答案
这里:
@Component
class ThreadExample implements Runnable
{
String file;
public void setFile(String file)
还有
Object ex is autowired so it will be instantiated only once.
那是行不通的。你有:
executor2.submit(ex);
您将相同对象传递给多个任务,这些任务应该并行执行特定的操作。更糟糕的是,您将不同的值放入该单个对象中,并以某种方式神奇地期望每个任务准确地看到您希望它看到的值。会发生什么:这些事情发生在不同的线程上,因此结果(可能)完全随机,也称为不确定性。
长话短说:当您需要完成多个“事情”时,随着时间的推移,您将无法使用“单例”容器来分派(dispatch)参数。 volatile
对此没有帮助,一点也没有。
答案是:为了使其工作,ThreadExample
不能是“单例”,因此将其变成单例的 @Component 注释必须消失。如果这样做与您的其他设计理念“冲突”,那么您必须退后一步并重新设计您的设计。
关于java - 多线程中的实例变量行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54516563/