首页 > 解决方案 > Instance variables behaviour in multithreading

问题描述

I am trying to run a program with 4 threads. I would like to know about the behaviour of instance variables in threading. In this I need to pass a value to the method. So, I am doing like this to pass the value and use it for further processing.

@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 returns list of file names. I am trying to do it in Spring. Here, 4 threads will work simultaneously. Object ex is autowired so it will be instantiated only once.

How file variable value would effect?

I am thinking like, one thread will try to set file through setFile(file) and it will be changed by another threads before using it in readFile.

How to overcome this issue? How to pass a value in multithreading? Will my problem be solved if I make 'file' as volatile ?

标签: javaspringmultithreading

解决方案


这里:

@Component
class ThreadExample implements Runnable
{
    String file;

    public void setFile(String file)

对象 ex 是自动装配的,因此它只会被实例化一次。

那是行不通的。你有:

executor2.submit(ex);      

您将同一个对象传递给多个任务,这些任务应该并行执行特定的操作。更糟糕的是,您将不同的值推送到单个对象中,并且以某种方式神奇地期望每个任务都能看到您希望它看到的值。会发生什么:这些事情发生在不同的线程上,所以结果(可能)是完全随机的,也就是不确定的。

长话短说:当您有多个“事情”需要完成时,随着时间的推移,您就不能使用“单例”容器来调度您的参数。volatile对此无济于事,一点也不。

答案是:为了使这项工作,ThreadExample不能是“单例”,因此将其变为单例的 @Component 注释必须消失。如果这样做与您的其他设计理念“冲突”,那么您必须退后一步并重新设计您的设计。


推荐阅读