Edd
Edd

Reputation: 107

Managing resource in Java multithreading

Suppose:

  1. There are 10 tasks
  2. There are 3 threads
  3. There are 3 arrayLists
  4. Every threads related to 1 arrayList

My question is : how to manage the resources? for example, first step 3 tasks will be executed using 3 threads and 3 arrayLists. Then whenever a thread is available, the 4th task will be executed along with available arrayList. How to do that in Java? please give me reference or source code.

public class NewClass {

    private Queue<Integer> availableCore = new LinkedList();

    public void manage() throws InterruptedException {
        ArrayList<ArrayList<Integer>> data = new ArrayList<>();
        data.add(new ArrayList<>());
        data.add(new ArrayList<>());
        data.add(new ArrayList<>());

        availableCore.add(0);
        availableCore.add(1);
        availableCore.add(2);

        ArrayList<Calculate> allThreads = new ArrayList<>();
        ExecutorService es = Executors.newWorkStealingPool(3);
        int threadCount = -1;

        int numOfTask = 10;

        while (numOfTask > 0) {
            if (!availableCore.isEmpty()) {
                System.out.println(availableCore.element());
                threadCount++;
                int core = availableCore.remove();
                allThreads.add(new Calculate(data.get(core), numOfTask, core));
                es.execute(allThreads.get(threadCount));
                numOfTask--;
            }
        }

        es.shutdown();
        boolean finished = es.awaitTermination(1, TimeUnit.DAYS);
        System.out.println("Done\n");

        for (int i = 0; i < data.size(); i++) {
            System.out.println(data.get(i));
        }
    }

    public class Calculate extends Thread {

        private ArrayList<Integer> data;
        private int start;
        private int core;

        public Calculate(ArrayList<Integer> data, int start, int core) {
            this.data = data;
            this.start = start;
            this.core = core;
        }

        @Override
        public void run() {
            this.data.add(start);
            availableCore.add(this.core);
        }

        public int getCore() {
            return core;
        }
    }
}

This code above is representing my actual problem. When I tried to run several times, sometimes I got an error in "availableCore.element()". It said that availableCore is empty, but I made a condition that make sure it is not empty.

if (!availableCore.isEmpty()) {
            System.out.println(availableCore.element());

Upvotes: 1

Views: 819

Answers (2)

dreamcrash
dreamcrash

Reputation: 51393

My question is : how to manage the resources? for example, first step 4 tasks will be executed using 4 core and 4 arrayList. Then whenever a core is available, the 5th task will be executed along with available arrayList. How to do that in Java? please give me reference or source code.

AFAIK, natively, Java does not have features to explicitly map a given thread to a given core (i.e., thread affinity). You can do it via explicit system calls such as in Linux OS using the taskset command. But this would require you to do a lot of working, and possibility lose portability in the way.

You would be better off using higher-level Java abstracts (e.g., ExecutorService) to deal with those low levels details for you. Send the tasks to a Thread Pool using the ExecutorService let the pool and ultimately the OS Threads scheduler deal with the mapping between threads/task.

Btw even using Java Thread Pools, there is no guarantee that the threads will be nicely mapped to separate cores.

Other languages, such as C/C++ might provide you with libraries that allow you to explicitly map cores to threads, for instance using OpenMP thread affinity features.


Based on your comment :

If I only send the tasks to a Thread Pool without managing the arrayList, it will consume a lot of memory. Suppose 1 have 100 tasks then it will need 100 arrayLists.. I want to reduce the memory consumption by using only 4 arrayList to be reused whenever a task is completed.

It sounds to me that you want to implement the producer-consumer pattern. One thread will be responsible for adding work to the Queue (i.e., ArrayLists) will the other threads request that work from the Queue and consume it.

Upvotes: 2

Volodya Lombrozo
Volodya Lombrozo

Reputation: 3454

As said @dreamcrash we can't map a thread to a core. But, you might use ExecutorService for your task. In this case, you will use thread per task, and your code will look like this:

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Cores {

    private static ExecutorService service = Executors.newFixedThreadPool(4);

    public static void main(String[] args) {
        List<String> first = List.of("1", "2", "3");
        List<String> second = List.of("1", "2", "3");
        List<String> third = List.of("1", "2", "3");
        List<String> fourth = List.of("1", "2", "3");
        List<String> fifth = List.of("1", "2", "3");

        sendToExecutor(first, second, third, fourth, fifth);

        service.shutdown();
    }

    @SafeVarargs
    public static void sendToExecutor(List<String>... lists) {
        for (List<String> list : lists) {
            service.execute(() -> handleWholeList(list));
        }
    }

    public static void handleWholeList(List<String> strings) {
        strings.forEach(s -> System.out.printf("String %s handled in thread %s%n", s, Thread.currentThread().getName()));
    }
}

And instead of hardcoded 4 threads:

private static ExecutorService service = Executors.newFixedThreadPool(4);

you could use the number of available processors:

private static ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

Upvotes: 1

Related Questions