Home > Net >  How to let threads manipulate the same list java
How to let threads manipulate the same list java

Time:05-07

I have an class where I define a list with an add and deletion method like here:

public class listClass{
    private List<T> someList = new ArrayList<>();

    public void add(){
        //adds to list
    }

    public void delete(){
        //deletes from list
    }
}

I have another class where I define two threads and a object from where I can access my list. One thread should use the add method to add continuously to the list and another thread should use the delete method to delete continuously from the list respective to there thread numbers:

public class threadClass extends Thread{
    private int threadNumber;
    public ThreadClass(int threadNumber){
        this.threadNumber = threadNumber;
    }

    listClass listClassObject = new listClass();

    public void run(){
        if(threadNumber == 1){
            while(true){/*add*/}
        }
        else if(threadNumber ==2){
                while(true){/*delete*/}
        }
    }
}

How can I do that so that both threads manipulating one and the same list?

My current implementation has a different class with a main method where I call the threads like here:

public static void main(String[] args){
        threadClass threadForAddingMediaFiles = new threadClass(1);
        threadClass threadForDeletionMediaFiles = new threadClass(2);
        threadForAddingMediaFiles.start();
        threadForDeletionMediaFiles.start();

The problem with the current implementation is that every thread creates his own instance of the list (which is clear to me because the list is in the same class) and so every thread does manipulate his own list and not one universal list.

CodePudding user response:

I think that happens because you are instantiating a new listClass inside each threadClass object so when you modify the list, you are actually modifing in each thread their own "local" copy. Try to instantiate the list in your main function and then pass it to your threads, so you'll have a single instance of your list class manipulated by both your threads.

public static void main(String[] args){
    listClass myList = new listClass();
    threadClass threadForAddingMediaFiles = new threadClass(1, myList);
    threadClass threadForDeletionMediaFiles = new threadClass(2, myList);
    threadForAddingMediaFiles.start();
    threadForDeletionMediaFiles.start();

Then modify your thread implementation:

public class threadClass extends Thread{
private int threadNumber;
private listClass listToHandle;
public ThreadClass(int threadNumber, listClass listToHandle){
    this.threadNumber = threadNumber;
    this.listToHandle = listToHandle;
}

public void run(){
    if(threadNumber == 1){
        while(true){/*add*/}
    }
    else if(threadNumber ==2){
            while(true){/*delete*/}
    }
}
}

Finally remember to to put both your add and delete method in your listclass as synchronized, or you'll have some problems regarding concurrent access.

public class listClass{
private List<T> someList = new ArrayList<>();

public synchronized void add(){
    //adds to list
}

public synchronized void delete(){
    //deletes from list
}
}

You may also give a look to CopyOnWriteArrayList, which is a thread-safe implementation of ArrayList. However, as said in the docs, this is ordinarily a costly implementation and might be not a suitable solution for your problem.

CodePudding user response:

In modern Java, we rarely address the Thread class directly. Instead, use the Executors framework added to Java 5. This has been covered in many existing Questions and Answers, so search to learn more.

Define your tasks as a Runnable rather than a Thread.

As for sharing your list manager across threads, make one instance. Be sure your list manager is thread-safe. Your current implementation is not thread-safe. One solution would be marking both the add and delete methods as synchronized.

Pass the one instance of your list manager object to the constructor of your Runnable task objects. Each Runnable keeps a reference to that list manager as a private member field. All your runnables then share the same single list manager.

Submit all your Runnable objects to an ExecutorService.

Again, all this has been covered many times already. Search to learn more.

CodePudding user response:

You can use Collections.synchronizedList() then no need to add synchronous into add/delete method. Create an instance of the ListClass and then pass it to both constructors of 2 threads.

class listClass
{
      private List<T> someList = Collections.synchronizedList(new ArrayList<>());    
}
  • Related