1

I have used a similar program as below to achieve multithreading to run parallel process but before completing few process my thread is moving to another (or) it is not completing the process completely, I am write some 5 files in parallel with data per thread where out of 5 sometimes 4 files are only writing. Please see the same code I refer,

private static final Random PRNG = new Random();

    private static class Result {
        private final int wait;
        public Result(int code) {
            this.wait = code;
        }
    }

    public static Result compute(Object obj) throws InterruptedException {
        int wait = PRNG.nextInt(3000);
        Thread.sleep(wait);
        return new Result(wait);
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException
          {
        List<Object> objects = new ArrayList<Object>();
        for (int i = 0; i < 1000; i++) {
            objects.add(new Object());
        }

        List<Callable<Result>> tasks = new ArrayList<Callable<Result>>();
        for (final Object object : objects) {
            Callable<Result> c = new Callable<Result>() {
                @Override
                public Result call() throws Exception {
                    return compute(object);
                }
            };
            tasks.add(c);
        }

        ExecutorService exec = Executors.newCachedThreadPool();
        // some other exectuors you could try to see the different behaviours
        // ExecutorService exec = Executors.newFixedThreadPool(3);
        // ExecutorService exec = Executors.newSingleThreadExecutor();
        try {
            long start = System.currentTimeMillis();
            List<Future<Result>> results = exec.invokeAll(tasks);
            int sum = 0;
            for (Future<Result> fr : results) {
                sum += fr.get().wait;
                System.out.println(String.format("Task waited %d ms",
                    fr.get().wait));
            }
            long elapsed = System.currentTimeMillis() - start;
            System.out.println(String.format("Elapsed time: %d ms", elapsed));
            System.out.println(String.format("... but compute tasks waited for total of %d ms; speed-up of %.2fx", sum, sum / (elapsed * 1d)));
        } finally {
            exec.shutdown();
        }
    }

May I know any better solution we can do for multi-threading to achieve once the process completes the thread should exit out from the process and I am using Java8,

Updated process code,

 public  String compute(String obj) throws InterruptedException {
          MyProcess myProc=new MyProcess(writeFiles(obj));
          myProc.generateReport();
          }
 public void processMethod() {        
            List<Callable<String>> tasks = new ArrayList<Callable<String>>();
                for (final String object : list) {
                        Callable<String> c = new Callable<String>() {
                            @Override
                            public String call() throws Exception {

                                return compute(object);
                            }
                        };
                        tasks.add(c);
                     }

            ExecutorService exec = Executors.newCachedThreadPool();

                    try {
                        long start = System.currentTimeMillis();
  List<Future<String>> results = exec.invokeAll(tasks);
                String sum=null;
                }
                finally {
                            exec.shutdown();
                        }
                        try {
                              exec.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                            } catch (InterruptedException e) {
            }
    }

Consider the writeFiles will read and write data from database to local file which is huge in memory and need to compare the 5 files which contains difference, where in this case for one time all the files are getting written and for others only one file is getting written and total time of thread is getting shared to all the pool-threads and within the time duration it is not possible to write all the files.

user3428736
  • 864
  • 2
  • 13
  • 33
  • @holi-java Correct. There's a further discrepancy introduced because `Thread.sleep` is not guaranteed to sleep for exactly the given time, but *at least* that amount of time - it could be significantly longer. – Michael Jul 14 '17 at 14:17
  • 1
    However `sleep()` could be interrupted, too... – Usagi Miyamoto Jul 14 '17 at 14:18
  • 1
    I have difficulties understanding what you actual problem is. I.e., I have no idea what “my thread is moving to another” or “is not completing the process completely” means. Especially with your example program that will simply run and print some numbers. What numbers do you get and what numbers do you expect instead? And what’s the relationship between these numbers and “my thread is moving to another” or “is not completing the process completely”? – Holger Jul 14 '17 at 15:26
  • You mention writing to files, which the given code does not do. – kewne Jul 14 '17 at 16:59

1 Answers1

2

This is because a Future whether is executed in concurrently or sequentially relies on the ExecutorService. so if you change the Executors.newCachedThreadPool() to Executors.newSingleThreadExecutor(), then the tasks is executed in sequentially rather than concurrently, then the elapsed time is almost the same with the total of wait time. for example:

List<Callable<Result>> tasks = asList(() -> compute(null), () -> compute(null));


ExecutorService exec = Executors.newSingleThreadExecutor();

try {
    long start = System.currentTimeMillis();
    List<Future<Result>> results = exec.invokeAll(tasks);
    int sum = 0;
    for (Future<Result> fr : results) {
        sum += fr.get().wait;
        System.out.println(String.format("Task waited %d ms",
                fr.get().wait));
    }
    long elapsed = System.currentTimeMillis() - start;
    System.out.println(elapsed / sum);
    //                         ^--- 1   
} finally {
    exec.shutdown();
}

AND you can see it in java.util.concurrent package summary in detailed as further:

Executor is a simple standardized interface for defining custom thread-like subsystems, including thread pools, asynchronous I/O, and lightweight task frameworks. Depending on which concrete Executor class is being used, tasks may execute in a newly created thread, an existing task-execution thread, or the thread calling execute, and may execute sequentially or concurrently.

holi-java
  • 29,655
  • 7
  • 72
  • 83
  • Thanks for explaining, but I need to improve the speed so I have used a thread pool and I need to run multiple threads parallely say 3000 and need to exit out once the thread completes.In a longer run the elapsed time for single and multiple thread is getting varied. Executors.newSingleThreadExecutor() is running in a sequential basis but I need to run things in a parallel where the thread needs to get exit only the process completed. please suggest if anything can be done to achieve the same. – user3428736 Jul 15 '17 at 04:30
  • @user3428736 could you give a minimum example to me, sir? I'm not good at english. did you want to execute 3000 tasks in parallel at a time? – holi-java Jul 15 '17 at 13:24
  • I need to run 3000 task in parallel where all the individual process will take more time so each thread exits before it completes it's task. – user3428736 Jul 17 '17 at 04:38
  • @user3428736 I'm sorry I'm late, but you shouldn't run 3000 task in parallel in a machine, this will make your program overflow or very slowly. but you can consider to using big data framework to run tasks in parallel of a cluster of nodes. – holi-java Jul 20 '17 at 14:10
  • In case if you need to run 200 task in parallel also the thread is getting time out , I need to do parallely but it should not get timeout for each task – user3428736 Jul 21 '17 at 08:03
  • @user3428736 :(, I'm sorry I'm forgot your comment, since it's weekend here. you can't run a huge tasks in parallel since there is no enough available processors in a machine. In contrast, it will makes your task slowly. maybe this can helped you: https://stackoverflow.com/questions/39935214/how-to-determine-the-max-possible-fixed-thread-pool-size – holi-java Jul 25 '17 at 11:28