【问题标题】:Is instantiating an object from an external class thread safe so long as it's done locally?只要在本地完成,从外部类线程实例化对象是否安全?
【发布时间】:2020-02-02 03:22:54
【问题描述】:

所以我正在通过一个我试图适应多线程模型的程序来学习并发、线程安全和其他相关主题。

这是我正在做的一些说明。

public class readerThread implements Runnable {

    private static BlockQueue<String> iqueue
    private static BlockingQueue<Object> oqueue
    private static ThreadLocal<java.util.ArrayList<File>> fileList = new ThreadLocal<java.util.ArrayList<File>>();  
    private static int FILE_BATCH_SIZE = 50;

    public void run() {
    fileList.set(new ArrayList<File>());
    ThreadLocal<Integer> i = new ThreadLocal<Integer>();    
    i.set(1);

        for (int y = i.get(); i<1000000; i.set(y++)) {

            try {

                File datafile = new File(iqueue.poll(86400, TimeUnit.SECONDS));

            } catch (InterruptedException e) {           
                e.printStackTrace();
            }

            if (datafile == null || datafile == POISION) {
                break;
            }

            fileList.get().add(datafile);
            ...
            ...

            if (fileList.get().size() == FILE_BATCH_SIZE || (iqueue.peek() == null) || (iqueue.peek() == POISON) ) {
                parseAndWrite();
                fileList.get().clear();         

            }






        }

    }



    public void parseAndWrite() {

        for (File f : fileList.get()) {
            Long fileTs = f.lastModified()
            String fileName = String.valueOf(f);

            Filelog filelog = new Filelog()
            Asset asset = new Asset()

            Parser parser = new Parser(f);
            // Parser returns an Asset
            asset = parser.parse()
            String assetTag = asset.getAssetTag();      


            filelog.setTimeStamp(fileTs);
            filelog.setFileName(fileName);
            filelog.setAssetTag(assetTag);
            filelog.setProcessed(false);

            HibernateWrapper.commit(filelog);

            oqueue.put(asset);


            .....
            .....


        }

    }



}

请忽略示例中的任何明显错误,因为它是仓促拼凑的。 实际上,几个 readerThreads 从阻塞队列中获取文件,将数据提取为对象并使用 Hibernate 将对象写入数据库。让我们假设 HibernateWrapper 是 100% 线程安全的;由于资产对象中的数据与从队列中取出的文件相关联,并且由于每个线程都在处理不同的文件,所以它是线程安全的吗? 如果我的术语不正确,请原谅我。基本上,我相信我之前的一些代码很奇怪,因为我观察到一些示例,其中写入的数据行与错误的对象相关联(例如,文件 foo 具有 bar 的资产标签)。

【问题讨论】:

  • '正在实例化一个对象......线程安全'是的。 “来自外部班级”:无关紧要。 “只要在本地完成”:毫无意义。您的代码无法编译。依赖于先前 try 块中代码成功的代码应该在该 try 块内。

标签: java multithreading concurrency thread-safety


【解决方案1】:

当线程之间存在共享状态时,线程安全是一个问题。如果您的代码使得每个线程都有自己的一组变量,那么代码是线程安全的。这比听起来更困难,因为您调用的其他函数或第三方库可能存在共享状态,因为它们可能会在线程之间引入共享状态。

您将fileList 用作线程本地是正确的,但看起来没有必要,因为您可以将它作为参数传递给parseAndWrite 方法。

你不需要使用线程局部i,因为它是一个堆栈变量,每个线程都有自己的副本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多