2

사용자가 파일을 거의 탐색하지 않고 대기열을 만들고 시작 업로드를 클릭하고 지정된 경로에서이 파일의 업로드를 시작하는 javaFX 프로젝트를 작성하고 있습니다. 이제 사용자가 일시 중지 버튼을 클릭하면 업로드 프로세스가 일시 중지되어야하고 다시 시작을 클릭하면 프로세스가 일시 중지 된 시점부터 다시 시작되어야합니다. 그래서 지금까지 Executors.newSingleThreadExecutor()를 통해 Objects (Files) 큐를 만들었습니다. 작업을 제출했습니다. 필자의 경우 taks 클래스는 Item으로 알려져있다. 일시 중지 버튼을 클릭하면 executorService의 shutdownnow() 메소드가 호출됩니다. 사용자가 이력서를 클릭하면 완전히 새로운 Executorservice 인스턴스를 만듭니다. 그러나 executor.execute 메서드를 통해 작업을 제출하면 현재 작업을 건너 뛰고 다음 작업을 다시 시작하는 식으로 진행됩니다. 그래서 마지막으로 실행했던 작업부터 시작해야합니다. 다음은 코드입니다.Executor 서비스 일시 중지 및 다시 시작 Java Executor 서비스

public class UploadManagerController implements Initializable { 

private static boolean checkRunning = true; 

private static String currentClient; 
private static int currentView = 0; 
private static int checkLastSelectedQueue = 0; 
private static Timeline fiveSecondsWonder; 
private List<File> uploadDir; 
private static long currentSelectedRow = -1; 
private static ThreadFactory threadFactory; 
private static ExecutorService executor; 
private static Thread t; 
private static LinkedHashMap<String, ObservableList> clientUploadInfo; 
private static HashMap<String, Long> clientUploadInfoCount; 
private static HashMap<String, String> clientUploadInfoTotalSize; 
private static HashMap<String, Double> clientUploadInfoTotalSizeLong; 


    public static class Item extends Task<Void> { 

    public SimpleStringProperty fileName = new SimpleStringProperty(); 
    public SimpleStringProperty fileSize = new SimpleStringProperty(); 
    public SimpleStringProperty ETA = new SimpleStringProperty(); 
    public SimpleStringProperty speed = new SimpleStringProperty(); 
    public SimpleStringProperty status = new SimpleStringProperty(); 
    public SimpleDoubleProperty progress = new SimpleDoubleProperty(); 
    public SimpleObjectProperty clientName = new SimpleObjectProperty(); 
    public SimpleStringProperty path = new SimpleStringProperty(); 
    public SimpleLongProperty id = new SimpleLongProperty(); 
    public File file; 
    public long time = 0; 

    // Getter and setter of above variables 

    @Override 
    protected Void call() throws Exception { 
     File filee = this.getFile(); 
     FileInputStream is = new FileInputStream(filee); 
     String mRecordingFile = "UserSpecifiedPath\\" + this.getFileName(); 

     File fl = new File(mRecordingFile); 
     if (fl.exists() && (this.getStatus().equals("error") != true || this.getStatus().equalsIgnoreCase("stopped") != true)) { 
      fl.renameTo(new File("UserSpecifiedPath\\" + Util.getTime() + "_" + fl.getName())); 

     } 

     boolean checkDelete = false; 
     for (String key : clientUploadInfo.keySet()) { 
      if (clientUploadInfo.get(key).contains(this)) { 
       checkDelete = true; 
       break; 
      } 
     } 
     if (checkDelete) { 
      java.nio.channels.FileChannel fc = is.getChannel(); 
      long totalSize = filee.length(); 
      long total = totalSize/10000; 
      java.nio.ByteBuffer bb = java.nio.ByteBuffer.allocate(10000); 

      byte[] bytes; 

      while (fc.read(bb) > 0) { 

       bb.flip(); 
       bytes = bb.array(); 
       File f = new File(mRecordingFile); 
       try (FileOutputStream fOut = new FileOutputStream(mRecordingFile, true)) { 
        fOut.write(bytes); 
       } 
         bb.clear(); 
      } 
     } 


     return null; 
    } 
} 

@Override 
public void initialize(URL url, ResourceBundle rb) { 
    clientUploadInfo = new LinkedHashMap<>(); 
      threadFactory = new ThreadFactory() { 
     @Override 
     public Thread newThread(Runnable r) { 

      t = new Thread(r); 
      try { 
       t.join(); 
      } catch (InterruptedException ex) { 
       System.out.println("inte"); 
      } 
      t.setDaemon(true); 
      return t; 
     } 
    }; 
    executor = Executors.newSingleThreadExecutor(threadFactory); 
} 

    @FXML 
private void startupload(ActionEvent event) { 
    ObservableList<Item> temp = FXCollections.observableArrayList(); 
    temp.addAll(clientUploadInfo.get(currentClient)); 
    currentView = 1; 
    checkRunning = true; 
    if (executor.isShutdown()) { 
     executor = null; 
     t=null; 
     threadFactory = null; 
     threadFactory = new ThreadFactory() { 

      @Override 
      public Thread newThread(Runnable r) { 
       t = new Thread(r); 
       try { 
        t.join(); 
       } catch (InterruptedException ex) { 
        Logger.getLogger(UploadManagerController.class.getName()).log(Level.SEVERE, null, ex); 
       } 

       t.setDaemon(true); 
       return t; 
      } 
     }; 
     executor = Executors.newSingleThreadExecutor(threadFactory); 


     for (Item itm : temp) { 
      if (itm.getStatus().equalsIgnoreCase("In Active") || itm.getStatus().equalsIgnoreCase("queued") || itm.getStatus().equalsIgnoreCase("error") || itm.getStatus().equalsIgnoreCase("stopped")) { 

       executor.submit(itm); 
      } 
     } 

    } else { 
     for (Item itm : temp) { 
      if (itm.getStatus().equalsIgnoreCase("In Active") || itm.getStatus().equalsIgnoreCase("queued") || itm.getStatus().equalsIgnoreCase("error") || itm.getStatus().equalsIgnoreCase("stopped")) { 

       executor.execute(itm); 
      } 
     } 
    } 
} 

@FXML 
private void stopUpload(ActionEvent event) { 
    checkRunning = false; 
    executor.shutdownNow(); 

} 
} 
내 영어 죄송

하지만, 나, 두 가지 방법이 startUpload는하고 STOPUPLOAD 자신있는 위의 코드에서, 을 설명하려고하자,이 두 가지 방법은 그래서 때 첫 번째 클릭, 자바 FX 버튼의 클릭에 호출 startUpload 버튼을 클릭하면 파일 추가 버튼을 클릭하여 유지 관리하는 clientUploadInfo.get (KEY) hasMap 파일을 업로드하기 시작합니다. 코드를 짧게 만들지는 언급하지 않았으며 Item 클래스는 모든 세부 사항을 전달합니다. 업로드 중지 버튼을 클릭하면 stopUpload 메서드가 호출됩니다. 업로드 시작 버튼을 다시 클릭하면 startUpload 메서드가 호출되지만 업로드 프로세스를 다시 시작합니다. 제 경우에는 업로드를 다시 시작하지만 다음 항목에서 현재 상태를 유지합니다 정지 버튼을 클릭했을 때의 상태를 표시합니다. 도움이 될 것입니다. 미리 감사드립니다.

+0

업로드 기능과 GUI 코드를 분리하는 것이 좋습니다. 이렇게하면 쉽게 테스트하고 변경할 수 있습니다. 이렇게하면 다른 사람들이 쉽게 이해할 수 있습니다. 귀하의 GUI 코드를 읽지 않고이 질문에 대답 할 수 있어야합니다. –

+0

안녕하세요. Peter Lawrey, GUI 코드를 제거했습니다. 다시 확인하십시오. – HEAT

답변

0

작업 <을 무시 하시겠습니까? > 클래스의 경우, executor 및 ThreadFactory를 사용하여 스레드의 인스턴스를 가져와야하는 동일한 스레드에서 일시 중지했다가 다시 시작하려면 executor를 다시 초기화하면 현재 스레드가 메모리에 남아 있고 링크가있는 것처럼 항상 건너 뜁니다. null을 넣더라도. 그래서 현재 스레드를 끝내면 일시 중지를 시도하고 현재 프로세스를 취소 할 수 없다는 메시지를 사용자에게 전달하는 대신 팝업을 표시하거나 Task 및 ThreadFactory를 재정의하고 현재 스레드의 ID를 얻으려고 제안합니다. 해당 스레드 만 다시 인 스턴스하십시오.

2

귀하의 요구 사항은 작업을 중지 할 수 있다는 것입니다. 집행자를 일시 중지하는 것은 일반적으로 매우 안전하지 않으므로 (자세한 내용은 Thread.suspend()의 javadoc을 참조하십시오), 집행자를 일시 중지 (집행)하여 구현하는 것이 좋습니다. 그것을 지원하지 않습니다. 그들이 안전하게 중단 할 수있는 작업은 정기적으로 시간에 waitWhileSuspended()를 호출 할

private boolean suspended; 

synchronized void suspend() { 
    suspended = true; 
} 

synchronized void resume() { 
    suspended = false; 
    notifyAll(); 
} 

synchronized void waitWhileSuspended() { 
    while (suspended) { 
     wait(); 
    } 
} 

:

훨씬 더 나은 디자인은 더 이상 진행하지 않는 것이 좋습니다 동안 작업 같은 뭔가 예를 들어, 대기해야하는 것 .

+0

그래, Runnable을 구현하여 Runnable 클래스를 만들어야합니다. 내가이 코드를 넣으려는 시도는 어디에서합니까? 현재 시도중인 작업을 중지하고 다시 활성화하지만 다음 작업에 도달하지 않을 것입니다. 또한 기다리는 동안 GUI가 응답하지 않습니다. – HEAT