我正在尝试运行具有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
中进行操作。
在这里,四个线程将同时工作。对象ex
是autowired
,因此它将仅被实例化一次。
file
变量值将如何影响?
我在想,一个线程将尝试通过setFile(file)
设置文件,并且在readFile
中使用它之前,另一个线程将对其进行更改。
如何克服这个问题?如何在多线程中传递值?
如果将'file'设为volatile
,我的问题会解决吗?
答案 0 :(得分:2)
这里:
@Component
class ThreadExample implements Runnable
{
String file;
public void setFile(String file)
和
对象ex是自动装配的,因此只能实例化一次。
那行不通。你有:
executor2.submit(ex);
您将相同对象传递给应该并行执行特定操作的多个任务。更糟糕的是,您将不同的值压入该单个对象,并以某种方式神奇地期望每个任务都能准确地看到您希望其看到的值。将会发生什么:这些事情发生在不同的线程上,所以结果(可能)是完全随机的,也就是不确定的。
长话短说:随着时间的流逝,当您需要处理多个“事情”时,您将无法使用“类单例”容器来调度参数。 volatile
对此无济于事,根本没有帮助。
答案是:为了使此工作有效,ThreadExample
不能是“单例”,因此必须将将其变成单例的@Component注释删除。如果这样做与您的其他设计思路“冲突”,那么您必须退后一步并重新设计。
答案 1 :(得分:1)
您必须使ThreadExample成为原型bean。
Bar
然后必须在应用程序上下文中注入
,而不是在ThreadCall中注入ThreadExample bean:amount
调用此代码时,基本上每个ThreadExample都是一个新bean。