我想用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
是autowired
所以它只能一次实例化。
如何file
变量的值会降低?
我的想法一样,一个线程将尝试通过setFile(file)
设置文件,它会被另一个线程readFile
使用前进行更改。
如何解决这个问题?如何通过多线程中的值?请问如果我做“文件”作为volatile
我的问题得到解决?
这里:
@Component
class ThreadExample implements Runnable
{
String file;
public void setFile(String file)
和
对象EX是自动装配,因此将只实例化一次。
这是行不通的。你有:
executor2.submit(ex);
您传递相同的对象,都应该做具体在什么并行多任务。更糟的是,你把不同的值成单个对象,并神奇地希望每个任务正好看到你发给它看到价值。会发生什么:这些事情发生在不同的线程,这样的结果是(可能是)完全随机的,又名不确定的。
长话短说:当你有多个“东西”需要做的,随着时间的推移,你就不能使用“单类”容器派遣您的参数。 volatile
不会与帮助,一点都没有。
答案是:为了使这项工作,ThreadExample
不能是“单身”,使@Component注解,把它变成一个单必须走开。如果与其他的设计理念这样做“碰撞”,那么你必须退后一步,返工您的设计。
你必须让ThreadExample为原型豆。
@Component
@Scope("prototype")
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
}
}
然后,而不是在ThreadCall注入ThreadExample豆你必须注入应用程序上下文:
@Component
class ThreadCall
{
@Autowired
ApplicationContext context;
public void testThread()
{
ExecutorService executor2 = Executors.newFixedThreadPool(4);
getFiles()
.stream()
.forEach(f-> {
ThreadExample ex= context.getBean(ThreadExample.class);
ex.setFile(f);
executor2.submit(ex);
});
}
}
当你调用这个代码,基本上每个ThreadExample将是一个新的bean。