1

この問題を解決しようとしましたが、難しいことがわかりました。

2 つのスレッドがあり、1 つはプロデューサーで、もう 1 つはコンシューマーです。すべて別クラス。2 つのスレッドは独立して実行されます。プロデューサーは、入力用に約 8 ~ 12 個のフォルダーをプールしています。次に、すべてのファイルを同時に翻訳し、「readyToLoad」という共有フォルダーに配置します。プロデューサー スレッドが完了すると、コンシューマー スレッドは「readyToLoad」フォルダーに入り、翻訳されたドキュメントの処理を開始します。

問題は、コンシューマーが翻訳されたドキュメントを処理している間、プロデューサーがさらに翻訳されたファイルを「readyToLoad」フォルダーに入れることを許可しないことです。

私の質問は、消費者が「readyToLoad」フォルダーをロックしないようにするにはどうすればよいですか? どうすればこの状況を管理できますか?

長いテキストで申し訳ありませんが、問題が発生している場所を理解するのに役立つと思います. 助けてくれてありがとう。

UPDATE : コンシューマー コードを追加しました (読み込みを実行し、読み込み中にファイルをロックするコード)。

public class LoadManager {
protected static final Logger logger = KCLogger.getLogger();
 ArrayList<Loader> threads = new ArrayList<Loader>();
 KCBLConfig config;
 private static final ExecutorService service = Executors.newFixedThreadPool(10);
 public LoadManager(KCBLConfig config) {
    this.config = config;
 }

public void start() throws Exception {
    logger.log(Level.INFO, "Starting loading threads.");
    try {
        TreeMap<String, ConnectionHandler> connectionHandlers = config.getConnectionHandlers();
        Iterator i = connectionHandlers.keySet().iterator();
        while (i.hasNext()) {

            ConnectionHandler connectionHandler = connectionHandlers.get((String) i.next());

            for (LoadFolder loadFolder : connectionHandler.getKcXMLFolders()) {
               Loader loader = new Loader(loadFolder.getId(), loadFolder, config.getConnectionHandlers());
               Thread loaderThread = new Thread(loader);
                loaderThread.start();   
               //service.submit(loader);
              // service.shutdown();
               //service.awaitTermination(1, TimeUnit.MILLISECONDS);
                threads.add(loader);
            }
        }
    } catch (Exception e) {
        logger.log(Level.SEVERE, "There was an error starting the loaders. Stopping all loader threads.", e);
        this.stop();
        throw e;
    }
    logger.log(Level.INFO, "All loader threads created. There are " + threads.size() + " loader threads");
}
4

3 に答える 3

0

私の理解が正しければ、プロデューサーとコンシューマーの間に通知メカニズムはありません。プロデューサーはファイルをフォルダーに保存し、コンシューマーはこのフォルダーからすべてのファイルを読み取り、別の場所に移動する無限ループを持っています。

それが問題です。これが私がそれを解決する方法です。

プロデューサとコンシューマはすべて、1 つの BlockingQueue インスタンスを共有する必要があります。プロデューサがファイルの作成を完了するたびに (ファイルが共有フォルダに完全に書き込まれると)、ファイルの名前がブロッキング キューに追加されます。

コンシューマーは、キューからファイル名を取得します。これはブロック操作であるため、ファイル名が使用可能になるまでコンシューマーはブロックされます。コンシューマーがキューからファイル名を取得すると、このファイル (およびこのファイルのみ) を読み取り、必要な操作を行います。

これにはいくつかの利点があります。

  • プロデューサーとコンシューマーが同時に 1 つのファイルにアクセスするリスクがない
  • 必要な数のプロデューサーとコンシューマーを持つことができます
  • 消費者はディレクトリを際限なくスキャンしません
  • あまりにも多くのファイルを生成しないようにキューに制限を設定し、消費者が生産者のペースに追いつく機会を与えることができます。
于 2013-07-19T10:26:58.407 に答える