Java promotion - Concurrent Programming

Java-Runnable ,Callable

hi, Hello, everyone. I'm a banana loving monkey. I've always wanted to write records about Java threads. I don't know what to write. After reading the thread part of a Book (Java core technology written for busy people), I feel I need to summarize;

In Java, the Runnable interface describes a task you want to run:

public interface Runnable {
	void run();
}

The code in the run method will be executed in a thread. Thread is a mechanism to execute a series of instructions, which is usually provided by the operating system. By using a separate processor or different time slices of the same processor, multiple threads run concurrently. When a task takes only a short time to execute, you want to have only one thread per processor instead of one thread per task, so as to avoid the overhead of switching between threads.
The executor class has a factory method for different types of executors. Call exec = executors newCachedThreadPool();
It will produce a program optimized executor with many short tasks or tasks that will consume a lot of time waiting.
Supplement: four creation methods of Java thread pool

  • newCachedThreadPool creates a cacheable thread pool. If the length of the thread pool exceeds the processing needs, idle threads can be recycled flexibly. If there is no recyclable thread, a new thread will be created.
  • newFixedThreadPool creates a fixed length thread pool, which can control the maximum concurrent number of threads. The exceeded threads will wait in the queue.
  • newScheduledThreadPool creates a fixed length thread pool that supports scheduled and periodic task execution.
  • Newsinglethreadexecution creates a singleton thread pool, which only uses a unique worker thread to execute tasks, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority).

Get the number of processors: int processors = runtime getRuntime(). availableProcessors();
View a demo:

    public static void main(String args[]) {
        Runnable hellos = () -> {
            for (int i = 0; i <= 1000; i++) {
                System.out.println("hello:" + i);
            }
        };
        Runnable goodbyes = () -> {
            for (int i = 0; i <= 1000; i++) {
                System.out.println("Goodbye" + i);
            }
        };
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.execute(hellos);
        executor.execute(goodbyes);
        executor.shutdown();
    }

Consider a problem: how to divide the calculation task into multiple subtasks, and each subtask calculates a part of the results. When all tasks are completed, you want to merge the results. A Callable sub task can be represented by a Callable sub task. Different from the run method of the Runnable interface, the call method of the Callable interface can return the result value:

public interface Callable<V> {
	V call() throws Exception;
}

To execute Callable, you need an instance of the ExecutorService interface, which is a sub interface of the Executor.
Take an example:

public class CallableDemo {
    public static long occurrences(String word, Path path) {
        try {
            //String contents = Files.readString(path);
            byte[] bytes = Files.readAllBytes(path);
            String contents = new String(bytes);
            //System.out.println("contents===" + contents);

            return Pattern.compile("\\PL+")
                    .splitAsStream(contents)
                    .filter(Predicate.isEqual(word))
                    .count();
        } catch (IOException ex) {
            return 0;
        }
    }

    public static Set<Path> descendants(Path p) throws IOException {
        try (Stream<Path> entries = Files.walk(p)) {
            return entries.collect(Collectors.toSet());
        }
    }
    
    public static void main(String[] args) throws
            InterruptedException, ExecutionException,
            IOException {
        String word = "String";
        Set<Path> paths = descendants(Paths.get("."));

        List<Callable<Long>> tasks = new ArrayList<>();
        for (Path p : paths) {
            /*tasks.add(new Callable<Long>() {
                @Override
                public Long call() throws Exception {//compute a result
                    return occurrences(word, p);
                }
            });*/
            tasks.add(() -> occurrences(word, p));
        }

        final int processors = Runtime.getRuntime().availableProcessors();
        System.out.println("cpus===" + processors);
        ExecutorService executor = Executors.newFixedThreadPool(processors);
        /**
         * invokeAll:Execute the given task and return the list of futures holding its status and results when all are completed
         * */
        List<Future<Long>> results = executor.invokeAll(tasks);
        long total = 0;
        for (Future<Long> result : results) {
            total += result.get();
        }

        System.out.println("Occurences of String:" + total);
        String searchWord = "occurences";
        List<Callable<Path>> searchTasks = new ArrayList<>();

        for (Path p : paths)
            searchTasks.add(
                    () -> {
                        if (occurrences(searchWord, p) > 0)
                            return p;
                        else throw new RuntimeException();
                    }
            );

        Path found = executor.invokeAny(searchTasks);
        System.out.println("found===" + found);
        executor.shutdown();
    }
}

Usually, tasks need to wait for the completion results of multiple subtasks. Instead of submitting subtasks one by one, you can use the invokeAll method to pass a collection of Callable instances to this method.
For example, in the example, calculate the frequency of a word in a group of files. For each file, you can generate a Callable that returns the statistical results of the file. They are then submitted to the executor. When all the tasks are completed, you get a set of future.

                                  Code Our Porter V1.0

Tags: Android

Posted by RossC0 on Wed, 27 Apr 2022 21:57:41 +0300