我是信号灯的新手,我有任何疑问。我有一个线程,该线程从文本文件A开始读取行,并将其写入其他文本文件B。我编写了这段代码,但是我不确定线程​​是否阻塞关键部分并正确同步。因为和其他线程可以使用这些文件进行操作。

public static void main(String[] args)  {

            Thread thread = new Thread(new ThreadManager());
            thread.start();

      }


线程类:

public class ThreadManager extends Thread {
      private Semaphore semaphore;

      public ThreadManager() {
            this.semaphore = new Semaphore(1);
      }

      public void run() {

            try {
                  this.semaphore.acquire();

                  BufferedReader br = null;
                  String line;
                  String fileNme = "threadLog.txt";
                  ArrayList<String> fileLines = new ArrayList<String>();
                  int numLine = 0;

                  File outFile = new File("$$$$$$$$.tmp");

                  // input
                  FileInputStream fis = null;
                  PrintWriter out = null;
                  try {
                        fis = new FileInputStream(fileNme);

                        // output
                        FileOutputStream fos = new FileOutputStream(outFile);
                        out = new PrintWriter(fos);
                  } catch (FileNotFoundException e2) {
                        // TODO Auto-generated catch block
                        e2.printStackTrace();
                  }
                  BufferedReader in = new BufferedReader(new InputStreamReader(fis));

                  try {
                        while ((line = in.readLine()) != null) {
                              fileLines.add(line);
                        }
                  } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                  }

                  if (!fileLines.isEmpty()) {
                        int middleLine = (int) Math.round(fileLines.size() / 2);
                        fileLines.add(middleLine, Thread.currentThread().getName());

                        for (int i = 0; i < fileLines.size(); i++) {
                              out.println(fileLines.get(i));
                        }

                        out.flush();
                        out.close();
                        try {
                              in.close();
                              new File(fileNme).delete();
                              outFile.renameTo(new File(fileNme));
                        } catch (IOException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                        }

                  }
                   this.semaphore.release();
            } catch (InterruptedException e3) {
                  // TODO Auto-generated catch block
                  e3.printStackTrace();
            }

      }

最佳答案

您不能保证使用信号量或同步块(或其他任何东西)仅对文件名进行同步访问。任何其他线程(或进程)仍然可以打开,读取或修改该文件,例如通过创建自己的FileOutputStream并传递相同的文件名。

尽管您可以肯定地构造代码以鼓励对文件的同步访问,至少在您的过程中,但这不能保证。因此,您必须对其他进程访问文件的可能性做出一些假设,并为其他线程如何访问文件并遵守这些规则定义(和记录)一些规则。

看来您只是在制作一个临时文件,所以您也可以考虑使用File.createTempFile()来减少使用相同文件名的可能性;在文件名中添加唯一性可能会有所帮助。

尽管我可以肯定地详细介绍特定的选项,但是您的问题并不清楚您的确切用法,并且如果没有更多信息,我能告诉您的最好的是,同步原语不能100%保证没有其他东西可以同时访问该文件了-您必须考虑自己的情况,并在通过代码提供这种保护与提供良好文档之间保持平衡,并遵循自己定义的规则。

顺便说一句,具有1个许可的信号量与互斥量相同,在这种情况下,您可能会发现synchronized blocks提供了更具吸引力的语法。

另外,不要忘记ReadWriteLock,这是另一个有用的工具,具体取决于您的访问模式和性能要求。

10-05 22:43
查看更多