2016-09-02 3 views
0

こんにちは私はスレッドでいくつかの問題があります。私はスレッドに1つのメソッドを実行したいと私はそれを行う方法を知らない。これを行う:私はこのような新しいオブジェクトのリストを持っています: インタフェースを実装するクラス(1)を作成します。Callable呼び出し可能なスレッドがvoidを返さないため、これを使用します。次に私はstring(url)のリストを持っています。次に、クラス(1)のようなオブジェクトのリストを作成します。次の私はexecutorを作成し、私はobcject nのスレッドJava Callable Poolスレッドは、この同じ時間にすべてを行います

public class UtlToImageConverter implements Callable<BufferedImage> { 

    private String url; 
    private static BufferedImage image; 

    public UtlToImageConverter(String url) { 
     this.url = url; 
     getImgFromPath(url); 
    } 

    public String getUrl() { 
     return url; 
    } 

    public void setUrl(String url) { 
     this.url = url; 
    } 

    public BufferedImage getImage() { 
     return image; 
    } 

    public void setImage(BufferedImage image) { 
     UtlToImageConverter.image = image; 
    } 

    public static BufferedImage getImgFromPath(String path){ 
     if(TestURLImage4.imgCache.get(path) != null){ 
      return TestURLImage4.imgCache.get(path); 
     } 
     else{ 
      URL url = null; 
      try { 
       url = new URL(path); 
      } catch (MalformedURLException e) { 
       e.printStackTrace(); 
      } 
      try { 
       image = ImageIO.read(url); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      System.out.println(TestURLImage4.imgCache.size()); 
      TestURLImage4.imgCache.put(path, image); 
      return image; 
     } 
    } 

    @Override 
    public BufferedImage call() throws Exception { 
     System.out.println("url " +url); 
     getImgFromPath(url); 
     System.out.println("url ok " +url); 
     return image; 
    } 

} 

次の私のリスト上のスレッドをしたい私はそれこれを行う:

ArrayList<UtlToImageConverter> threadList = new ArrayList<>(); 
      for(String url : URLPathList){ 
       threadList.add(new UtlToImageConverter(url)); 
      } 
      ExecutorService executor = Executors.newFixedThreadPool(10); 

     try { 
//   executor.invokeAll(threadList, 1000L, TimeUnit.SECONDS); 
      executor.invokeAll(threadList); 
//   executor.invokeAny(threadList); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
//  } catch (ExecutionException e) { 
//   e.printStackTrace(); 
     }  
+1

あなたは質問をするのを忘れていましたが、明らかに2つの主な問題があります:(1)あなたのスレッドプールはスレッドを1つしか持たず、並列にタスクを実行する必要があります。 'newFixedThreadPool()'呼び出しで使いたいと思います。 (2)すべてのタスクが実行されて終了するようにするには、 'invokeAll()'を使う必要があります。 'invokeAny()'はすべてのタスクを実行しますが、そのうちの1つが終了するのを待ってから、他のタスクをキャンセルします。 –

+0

@AndrewLyginいいえこれに変更します\t \t ExecutorService executor = Executors.newFixedThreadPool(10);しかし、もし私が1または2または10の数字を持っていれば、これは同じように動作します。 –

+0

@AndrewLygin newFixedThreadPoolの変更番号は変更されません。 –

答えて

1

問題は、あなたがのコンストラクタからgetImgFromPath()を呼び出すことですUtlToImageConverter。したがって、すべてのイメージは、実行者に送信される前に、順次、インスタンシエーションのプロセスでダウンロードされます。エグゼキュータはキャッシュからそれらを取得するだけなので、違いは見えません。コンストラクタからgetImgFromPath()コールを削除し、エグゼキュータに実際のダウンロードを実行させます。

+0

どのように見えるか教えてください。なぜ私はそれを行うことができないのですか? –

+0

コンストラクタからコード 'getImgFromPath();を削除するだけです(コードの8行目です)。 –

+0

私はあなたがコンストラクタからこの行を削除すると言ったことを行うが、私は1スレッドプールまたは10または20または100を持っている場合は、この同じです –

関連する問題