【问题标题】:issue at handling multithreading in java (using ThreadLocal) [duplicate]在java中处理多线程的问题(使用ThreadLocal)[重复]
【发布时间】:2014-07-06 00:41:26
【问题描述】:

我在使用 java 中的多线程时遇到了一些问题。我是一名学生,Java 初学者,只是为了娱乐目的而开发这个(抱歉语法不好,英语不是我的第一个语言)。

我正在做一个供个人使用的小型下载器,它最多接受 5 个同时下载。每次下载都由不同的线程处理(不是普通线程,只是 swingworker,我也使用它来避免 UI 冻结。)。

   public static String PATH;                   //File path
   public static String NAME;                   //File name

   //Download Method
   public void download() { 
      //download code...
   }

此方法运行良好(它会下载一个文件,然后按预期将其保存到硬盘中)。但是,当我想同时进行两次(或更多)下载时,问题就来了。考虑我同时下载两个文件,文件 A文件 B。当我开始下载A时,字符串PATHNAME根据文件A获取其值,一切OK。然后,我开始下载 B,之前存储的 A 值被替换为对应于 B 的值。所以当A下载完成后,文件名与下载B完成时B应该有的相同。 继续,我需要同一变量的不同实例,它们将包含不同且独立的值。

我开始研究该主题并导致ThreadLocal变量。这种类型的变量应该在每个正在运行的线程中发生变化,这正是我所需要的。 我试图在我的代码中实现这一点。

   public static String PATH;                   //File path
   public static String NAME;                   //File name

   public ThreadLocal<String> TL_PATH =  new ThreadLocal<String>();
   public ThreadLocal<String> TL_NAME =  new ThreadLocal<String>();

   public void download() { 
   //Try to set ThreadLocal to PATH and NAME variables.
       TL_NAME.set(NAME);
       TL_PATH.set(PATH);

   //download code... 

   }

一旦我这样做了,一切都一样了。我的代码有什么问题? (在任何情况下都不会抛出异常,就像我之前解释的那样)

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    你做错了

    您应该实现Runnable 并让它获取下载到的网址和路径。

    使用池中的ExecutorService 设置为5 线程。

    管理实现Runnable的类的各个实例。

    这是一个例子:

    import javax.annotation.Nonnull;
    import java.io.File;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    public class Q24591731
    {
        private static final ExecutorService EXECUTOR_SERVICE;
    
        static
        {
            EXECUTOR_SERVICE = Executors.newFixedThreadPool(5);
        }
    
        public static void main(final String[] args)
        {
            final Download d1;
            try { d1 = new Download(new URL("www.someurl.to.download.com"), new File("dest/file/name")); }
            catch (MalformedURLException e) { throw new RuntimeException(e); }
            // create as many downloads as you need how ever you want.
            EXECUTOR_SERVICE.submit(d1);
            // when all are submitted
            EXECUTOR_SERVICE.shutdown();
            try
            {
                EXECUTOR_SERVICE.awaitTermination(1, TimeUnit.MINUTES);
            }
            catch (InterruptedException e)
            {
                System.exit(1);
            }
    
        }
    
        public static class Download implements Runnable
        {
            private final URL url;
            private final File dest;
    
            public Download(@Nonnull final URL url, @Nonnull final File dest)
            {
                this.url = url;
                this.dest = dest;
            }
    
            @Override
            public void run()
            {
                // download the file and write it to disk
            }
        }
    }
    

    读者练习:

    ExecutorCompletionService 是一个更合适的解决方案,但它涉及更多一点,并且与Callable 而不是Runnable 一起使用效果最好。尤其是像这样的batch processing。但我在这里有其他答案的示例,不想再重复该解决方案。

    【讨论】:

    • 目前对我来说相当棘手和复杂。我会看看我是否可以阅读更多关于它的内容。我的代码有很多类,我不知道我可以在其中的哪个类中实现它。不过,谢谢你的回答。现在我知道从哪里开始了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-01
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 2016-11-27
    相关资源
    最近更新 更多