How to force threads to perform certain functions?

1

10 threads are agreed upon when the Client connects to the server, when the Client asks for a word, the server wakes up these threads and they will go through a list of tasks.

What I wanted to happen: whenever a thread scans () that word, remove that task from the list so that when the next one ran that task it was not already on the list.

What happens: more than one thread starts scanning (), and all scan () the first task.

public  class ThreadSearcher extends Thread{
    private int x;

    public ThreadSearcher(int x){
        this.x=x;   

    }


    @Override
    public void run(){

        while(!interrupted()){

            System.out.println("Comecei a correr:" + x); 
            try {

                Tarefa t = getTarefas().get(0);
                scan(t);
                System.out.println("Sou a "+ this.x + " e fiz o scan de " + t.getStart() + "a" + t.getFinish());
                System.out.println("Sou a " + x + "antes de remover tinha " + tarefas.size());
                tarefas.remove(t);
                System.out.println("Sou a " + x + "depois de remover tinha " + tarefas.size());

                System.out.println("removi a" + t);



            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }



        }
    }
}
    
asked by anonymous 07.12.2017 / 02:24

1 answer

2

This is a common multithreading problem.

Basically, you are sharing a ArrayList or similar structure for the various threads without any control or synchronization mechanism, thus violating the consistency of your program.

There are several ways to resolve this. I'll cite two.

Manual synchronization

Synchronize the threads against the shared list so that only one thread can modify the object at a time.

Example using synchronized :

//recupere a lista
List<Tarefa> tarefas = getTarefas();
Tarefa t;
//a partir daqui, somente uma thread execute de cada vez
synchronized (tarefas) {
  //o método remove de uma lista retorna o elemento removido
  t = tarefas.remove(0);
}
//processa o elemento não compartilhado t fora do bloco sincronizado,
//caso contrário vai enfileirar cada elemento
scan(t)

Thread-safe structure

There are some Java objects that allow you to perform operations directly across multiple threads in a secure way.

For example, LinkedBlockingDeque with your method poll() can be used, then you just have to list your tasks using this object type and its threads like this:

//pega o primeiro item da lista, removendo-o
Tarefa t = getTarefas().poll();
//null significa que a lista estava fazia
if (t != null) {
    scan(t)
}

In addition, the take() method can be used if you want the thread to wait for the list to have some element. Instead of returning null if the list is empty as in poll() , the take() method blocks the thread and waits for something to be added.

    
09.12.2017 / 00:28