0

我正在使用一个单例,由于某种原因无法正常工作,不知道为什么

  private static ConnectionUtility instance;

  public static ConnectionUtility getInstance() {
     if(instance == null){
         instance = new ConnectionUtility();
     }
     return instance;
  }

在上面显示的代码中,第二次执行此代码时,instance 不为空,已经创建了一个实例,因此第二次执行此代码时应直接转到返回实例行并跳过instance = new ConnectionUtility() 行。然而,在第二次迭代中,它会在已经存在的情况下尝试创建 ConnectionUtility 对象的另一个实例。为什么要这样做?如何解决这个问题?

完整代码发布在下面:对于 3 个类 ConnectionUtility 和 MultiThreader 和 Start

  public class Start {

   public static void main(String args[]) {

  ConnectionUtility.getInstance();

 } // end main

} // end Start

    public class ConnectionUtility extends javax.swing.JFrame
    implements  MultiThreader.OnSendResultListener {

    private static ConnectionUtility instance;

    public static ConnectionUtility getInstance() {
     if(instance == null){
         instance = new ConnectionUtility();
     }
     return instance;
    }

   private ConnectionUtility() {

     initComponents();
     this.setVisible(true);

     serverRunner();

     File fileOne = new File("C:/DBFiles");
     if(!fileOne.exists()){
         fileOne.mkdir();
     }

     File fileTwo = new File("C:/DBFilesOut");
     if(!fileTwo.exists()){
         fileTwo.mkdir();
     }  

  }
public void serverRunner(){

      runner = true;

       try {
        serversocket = new ServerSocket(6789, 100);

         System.out.println();

    } catch (IOException ex) {
        Logger.getLogger(ConnectionUtility.class.getName()).log(Level.SEVERE, null, ex);
    }

      while(runner){

         try {
             socket = serversocket.accept();

   addAndDisplayTextToString("new connection, inet socket address >>> " + socket.getPort());
   System.out.println(displayString);


         } catch (IOException ex) {
             Logger.getLogger(ConnectionUtility.class.getName()).log(Level.SEVERE, null, ex);
         }

      //     MultiThreader multi = new MultiThreader(socket, this);
         MultiThreader multi = new MultiThreader(socket);
           Thread t = new Thread(multi);
           t.start();

      }  // end while runner loop

  } // end serverRunner method

   public static void addAndDisplayTextToString(String setString){

   StringBuilder stb = new StringBuilder(displayString);

   setString = setString + "\n";

   if(stb.toString() == ""){
   stb.append(setString);
   }else if(stb.toString() != ""){
       stb.insert(0, setString);
   }

    int counter = 0;

  for(int i = 0; i < stb.length(); i++){
      if(stb.substring(i, i + 1).equals("\n")){
           counter++;
      }
  }

  // get the last index of "\n"
  int lastIndex = stb.lastIndexOf("\n");

  int maximum = 4;
  if(counter >= maximum){

      stb.delete(lastIndex, stb.length());
      System.out.println();

  }

  displayString = stb.toString();

 }

@Override
public void onStringResult(String transferString) {
   addAndDisplayTextToString(transferString);
   jTextArea1.setText(displayString);
   System.out.println("RETURNED TRING " + transferString);

}

} // class ConnectionUtility

public class MultiThreader implements Runnable {


  public MultiThreader(Socket s) {
    socket = s;
stpe = new ScheduledThreadPoolExecutor(5);
    listener = ConnectionUtility.getInstance();

}

@Override
public void run() {

    long serialNumber = 0;
    int bufferSize = 0;

     // get input streams
    try {
    bis = new BufferedInputStream(socket.getInputStream());
    dis = new DataInputStream(bis);
    } catch (IOException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

    sendStatus("New connection strarted");

     // read in streams from server
    try {        
        fileSizeFromClient = dis.readInt();
         sendStatus("File size from client " + fileSizeFromClient);
         serialNumber = dis.readLong();
         sendStatus("Serial mumber from client " + serialNumber);
    } catch (IOException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

     try {
        bufferSize = socket.getReceiveBufferSize();
         sendStatus("Buffer size " + bufferSize);
    } catch (SocketException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

    String serialString = String.valueOf(serialNumber);

    File fileDirectory = new File("C:" + File.separator + "DOWNLOAD" + File.separator + serialNumber + File.separator);
    fileDirectory.mkdir();

    File file = new File("C:" + File.separator + "DOWNLOAD" + File.separator + serialNumber + File.separator + "JISSend.pdf");
    try {
        file.createNewFile();
    } catch (IOException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }
    try {
    fos = new FileOutputStream(file);
    bos = new BufferedOutputStream(fos);
    dos = new DataOutputStream(bos);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

    int count = 0;
    byte[] buffer = new byte[fileSizeFromClient];

    try {

      int totalBytesRead = 0;

       while(totalBytesRead < fileSizeFromClient){
       int bytesRemaining = fileSizeFromClient - totalBytesRead;
       int bytesRead = dis.read(buffer, 0, (int)Math.min(buffer.length, bytesRemaining));

        if(bytesRead == -1){
           break;
         }else{

            dos.write(buffer, 0, bytesRead);
            totalBytesRead += bytesRead;

        }
    }

        } catch (IOException ex) {
            Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {

            dos = new DataOutputStream(socket.getOutputStream());

        } catch (IOException ex) {
            Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
        }

        stpe.schedule(new CompareFiles(), 0, TimeUnit.SECONDS);
        stpe.schedule(new CloseResources(), 2, TimeUnit.SECONDS);

  } // end run method

  public class CompareFiles implements Runnable {

    @Override
    public void run() {

  int returnInt = 0;
  FileInputStream fis = null;

    File file = new File("C:/DOWNLOAD/JISSend.pdf");
    try {
        fis = new FileInputStream(file);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

        int fileLength = (int) file.length();

        sendStatus("Size of database file sent " + fileLength);

         if(fileLength == fileSizeFromClient){

         sendStatus("File sent to server, Successful");   
         returnInt = 1;

         }else if(fileLength != fileSizeFromClient){

         sendStatus("ERROR, file send failed");   
         returnInt = 2;

         }
        try {
            dos.writeInt(returnInt);
        } catch (IOException ex) {
            Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
        }

    } // end run method
   } // end of class comparefiles

   public class CloseResources implements Runnable {

    @Override
    public void run() {

    try {
    fos.flush();
    bis.close();
    bos.close();
    dis.close();
    dos.close();
    socket.close();
    } catch (IOException ex) {
            Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

    } // end run method
  } // end of class closeResources

   public interface OnSendResultListener {
    public void onStringResult(String transferString);
  }

  public void sendStatus(String status){
 listener.onStringResult(status);
  }

  } // end class mulitthreader

编辑:这里是第二次调用 ConnectionUitlity 对象的地方,在 Multithreader 类的构造函数中,当它被调用以在 connectionUtility 中创建新的多线程类时

 public MultiThreader(Socket s) {

    socket = s;
stpe = new ScheduledThreadPoolExecutor(5);
    listener = ConnectionUtility.getInstance();


}
4

1 回答 1

1

来自评论

在多线程环境中,您的getInstance方法应该是同步的,或者使用双重检查锁定。构造函数也应该是私有的,以避免在类之外创建。你应该检查http://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-with-examples

于 2013-10-02T06:47:02.480 回答