Programming basics - Techniques and Tricks V -

Joe

Thành viên VIP
21/1/13
2,935
1,304
113
(Cont. of Programming basics - Techniques and Tricks IV -)

Hi

8) Thread or Task or Process? I have showed you the differences and the commonness of Runnable an Callable. Both, the Runnable and the Callable, are best-suited for short-life processes that are executed inside a Pool (Thread or TaskPool). Outside the pool they are "awkward" and requires a lot of work for their execution. What is about Thread and Task or Process? Again, on the Web you could dig out tons of blogs about the three. Hence, I just talk about their usage and when / how they are the best choice. In general Process is a synonym of Task. But in JAVA it is a NATIVE task of OS. First, for the clarity:
  • Thread won't return anything. Also there is NO feedback, nor Communication between Thread and its parents. Thread is 100% independent from the main thread. Problem arises when a Thread runs into problems and the main thread (i.e. parents) has no chance to check, nor to amend.
  • Task always returns something. An object, a primitive or even a "null". That is the feedback to the parents so that they can determine what to do with the feedback. Because a Task is always on its own it needs a "vehicle", or to be precise: an environment, to run. The vehicle could be a ThreadPool or a ForkJoinPool. With the feedback the main thread can fine-tune its process or to amend the outcome.
  • Process is in JAVA a native task of JVM Guest OS (Linux or Window, etc.). In this case the main thread can only accept the outcome delivered from the launched process.
From this viewpoint Thread is a light-weight Task. Meaning: a Task is a JVM process that can be fully independent from the parents while a Thread is still dependent from its parents resources. The following show you the fundamental difference between Thread and Task (which is an extension of the API RecusiveTask):
PHP:
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
public class Test7  {
  public Test7(String[] A) {

    // // Using a Thread to do the copy file-to-file
    new Thread() {
      public void run() {
        try (FileInputStream fin = new FileInputStream(A[1]);
             FileOutputStream fou = new FileOutputStream(A[2])) {
          byte[] cont = new byte[fin.available()];
          int n = fin.read(cont);
          fou.write(cont,0,n);
          fou.flush();
          fin.close();
          fou.close();
          System.out.println("\nCopy "+A[1]+" to "+A[2]+" is done!\n");
        } catch(Exception ex) {
          System.out.println("Can't copy "+A[1]+" to "+A[2]+". Reason:"+ex.toString());
        }
      }
    }.start();

    // Using Recursive task to list all files in a directory and its subditectories
    ArrayList<String> list = new ArrayList<String>();
    class loadFiles extends RecursiveTask<Void> {
      public loadFiles(String P) {
        this.P = P;
      }
      private String P;
      protected Void compute( ) {
        try {
          File[] files = new File(P).listFiles();
          List<loadFiles> tasks = new ArrayList<loadFiles>();
          for (File fi:files) {
            String name = P + File.separator + fi.getName();
            if (fi.isFile()) { // is a File
              list.add(name);
            } else { // recursive to subdirectory
              loadFiles lf = new loadFiles(name);
              lf.fork(); // recursive
              tasks.add(lf);
            }
          }
          for (loadFiles lf : tasks) lf.join();
        } catch (Exception ex) { }
        return null;
      }
    }
    // The Vehicle is the CommonPool of ForkJoinTask
    Future<Void> f = ForkJoinPool.commonPool().submit(new loadFiles(A[0]));
    try {
      f.get(); // from folder
      for (int i=0, s=list.size(); i < s; ++i) System.out.println((i+1)+".File:"+list.get(i));
    } catch (Exception ex) { }
  }
  //
  public static void main(String... A) {
    if (A.length != 3) {
      System.out.println("Usage: java Test7 directoryName fileName_1 anyName_2");
      System.exit(0);
    }
    new Test7(A);
  }
}
Code:
C:\java\Test>javac -g:none -d ./classes Test7.java

C:\java\Test>java Test7 c:\java Test7.java Test7a.java

Copy Test7.java to Test7a.java is done!

1.File:c:\java\basic.jpg
2.File:c:\java\basic.txt
3.File:c:\java\basic_1.txt
   ...
207.File:c:\java\Test\classes\Test7$1.class
208.File:c:\java\Test\classes\Test7$1loadFiles.class
209.File:c:\java\Test\classes\Test7.class

C:\java\Test>
You get a list of all filenames with the "RecursiveTask". As in previous lesson (Techniques and Tricks IV) you can use the FutureTask<?> API to do the copy, too. However, as a Task, FutureTask requires a vehicle to run: either a Thread or a Pool like the RecursiveTask. The same copy "Process" is carried out by JAVA API Runtime/Process.
PHP:
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
public class Test7a  {
  public Test7a(String[] A) {
    // THREAD: this a Thread that does the copy a file to a file
    new Thread() {
      public void run() {
        try (FileInputStream fin = new FileInputStream(A[1]);
             FileOutputStream fou = new FileOutputStream("THREAD_"+A[2])) {
          byte[] cont = new byte[fin.available()];
          int n = fin.read(cont);
          fou.write(cont,0,n);
          fou.flush();
          fin.close();
          fou.close();
          System.out.println("Copy "+A[1]+" to THREAD_"+A[2]+" is done!");
        } catch(Exception ex) {
          System.out.println("Can't copy "+A[1]+" to THREAD_"+A[2]+". Reason:"+ex.toString());
        }
      }
    }.start();

    // TASK: Using FutureTask to do the copy
    FutureTask<Void> fTask = new FutureTask<>(()->{
      try (FileInputStream fin = new FileInputStream(A[1]);
           FileOutputStream fou = new FileOutputStream("TASK_"+A[2])) {
        byte[] cont = new byte[fin.available()];
        int n = fin.read(cont);
        fou.write(cont,0,n);
        fou.flush();
        fin.close();
        fou.close();
        System.out.println("Copy "+A[1]+" to TASK_"+A[2]+" is done!");
      } catch(Exception ex) {
        System.out.println("Can't copy "+A[1]+" to TASK_"+A[2]+". Reason:"+ex.toString());
      }
      return null;
    });

    new Thread(fTask).start();
    try {
      fTask.get(); // from folder
    } catch (Exception ex) { }

    // PROCESS: using Windows COPY command
    try {
      Process p = Runtime.getRuntime().exec("cmd /c copy /Y "+A[1]+" PROCESS_"+A[2]);
      InputStream inp = p.getInputStream();
      byte[] rep = new byte[248];
      int n = inp.read(rep);
      inp.close();
      System.out.println("Process Returned:"+new String(rep, 0, n));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  //
  public static void main(String... A) {
    if (A.length != 3) {
      System.out.println("Usage: java Test7 directoryName fileName_1 anyName_2");
      System.exit(0);
    }
    new Test7a(A);
  }
}
Code:
C:\java\Test>javac -g:none -d ./classes Test7a.java

C:\java\Test>java Test7a C:\java Test7a.java aCopy.txt

Copy Test7a.java to TASK_aCopy.txt is done!
Copy Test7a.java to THREAD_aCopy.txt is done!
Process Returned:        1 file(s) copied.


C:\java\Test>dir *aCopy.*

15.02.2020  10:02             2.189 PROCESS_aCopy.txt
15.02.2020  10:03             2.189 TASK_aCopy.txt
15.02.2020  10:03             2.189 THREAD_aCopy.txt

C:\java\Test>
The results are the same: 3 files with the same content.

(cont.)
 
Sửa lần cuối:
  • Like
Reactions: jos le