6

result.txtというファイルにprintln()関数を使用して書き込むスレッドが20個あります。それらすべてを同期するにはどうすればよいですか?

プログラムを実行するたびに、results.txtのテキストの行数が異なることに注意してください。

ありがとうございました。

4

3 に答える 3

29

ファイルに書き込むための同期メソッドを含むクラスを介してファイルにアクセスします。メソッドを実行できるのは、一度に1つのスレッドのみです。

シングルトンパターンがあなたの問題に合うと思います:

package com.test.singleton;

public class Singleton {
    private static final Singleton inst= new Singleton();
    
    private Singleton() {
        super();
    }
    
    public synchronized void writeToFile(String str) {
        // Do whatever
    }
    
    public static Singleton getInstance() {
        return inst;
    }
    
}

ファイルに書き込む必要があるたびに、呼び出す必要があるのは次のとおりです。

Singleton.getInstance().writeToFile("Hello!!");
于 2012-04-05T10:42:04.470 に答える
7

質問が重複しています...回答が重複しています。私がここで言ったように:

ファイルをとして保持できる場合は、次のFileOutputStreamようにロックできます。

FileOutputStream file = ...
....
// Thread safe version.
void write(byte[] bytes) {
  try {
    boolean written = false;
    do {
      try {
        // Lock it!
        FileLock lock = file.getChannel().lock();
        try {
          // Write the bytes.
          file.write(bytes);
          written = true;
        } finally {
          // Release the lock.
          lock.release();
        }
      } catch ( OverlappingFileLockException ofle ) {
        try {
          // Wait a bit
          Thread.sleep(0);
        } catch (InterruptedException ex) {
          throw new InterruptedIOException ("Interrupted waiting for a file lock.");
        }
      }
    } while (!written);
  } catch (IOException ex) {
    log.warn("Failed to lock " + fileName, ex);
  }
}
于 2012-04-05T15:09:16.327 に答える
2

1つのファイルにデータを書き込む予定です。したがって、ファイル全体をロックしようとする場合は、単一のスレッドを使用してこのジョブを実行することをお勧めします。20個のスレッドを生成しますが、メソッドを呼び出すたびに実行されているスレッドは1つだけですが、他のスレッドはロックを待機しているだけです。

RandomAccessFileファイルへのデータの書き込みに使用することをお勧めします。次に、各スレッドは、ファイル全体をロックすることなく、いくつかの一意のデータをファイルに書き込むことができます。

次のようないくつかのデモコード

try {
    final RandomAccessFile file = new RandomAccessFile("/path/to/your/result.txt", "rw");
    final int numberOfThread = 20;
    final int bufferSize = 512;
    ExecutorService pool = Executors.newFixedThreadPool(numberOfThread);
    final AtomicInteger byteCounter = new AtomicInteger(0);
    final byte[] yourText = "Your data".getBytes();
    for (int i = 0; i < yourText.length; i++) {
        pool.submit(new Runnable() {
            @Override
            public void run() {
                int start = byteCounter.getAndAdd(bufferSize);
                int chunkSize = bufferSize;
                if (start + bufferSize > yourText.length) {
                    chunkSize = yourText.length - start;
                }
                byte[] chunkData = new byte[chunkSize];
                System.arraycopy(yourText, start, chunkData, 0, chunkSize);
                try {
                    file.write(chunkData);
                } catch (IOException e) {
                    //exception handle
                }
            }
        });
    }
    file.close();
} catch (Exception e) {
    //clean up
}
于 2012-04-05T11:20:05.207 に答える