I'm practicing threading and after a while I can't get to the point where the run() method inside the Requirement_1.java class recognizes objects of type ArrayList() , should I create the objects inside the run( ) ? I appreciate any suggestion. I paste the main class Main_Activity01.java and its corresponding class Requirement_1.java in order of appearance. What the activity asks for is to get the list of prime and non-prime numbers using a thread for each one.
import java.util.ArrayList;
import java.util.Scanner;
public class Main_Actividad01 {
public static void main(String[] args) {
ArrayList<Integer> lista_primos = new ArrayList<Integer>();
Requerimiento_1 lista_primos1 = new Requerimiento_1(lista_primos);
Thread t1 = new Thread(lista_primos1);
t1.setName(" Hilo 1 ");
ArrayList<Integer> lista_Noprimos = new ArrayList<Integer>();
Requerimiento_1 lista_Noprimos1 = new Requerimiento_1(lista_Noprimos);
Thread t2 = new Thread(lista_Noprimos1);
t2.setName(" Hilo 2 ");
try {
Thread.sleep(500);
}catch (InterruptedException e) {
e.printStackTrace();
}
t1.start();
t2.start();
System.out.println("Esta es la lista de primos "+lista_primos + " esta en la lista de los No primos"+ lista_Noprimos);
}
}
public class Requirement_1 implements Runnable{ private ArrayList list;
Scanner sc = new Scanner(System.in);
public Requerimiento_1() {
super();
}
public Requerimiento_1(ArrayList<Integer> lista) {
super();
this.lista = lista;
}
public ArrayList<Integer> getLista() {
return lista;
}
public void setLista(ArrayList<Integer> lista) {
this.lista = lista;
}
public void add(ArrayList<Integer> req) {
this.lista = req;
}
public synchronized ArrayList<Integer> esprimo(ArrayList<Integer> lista_Noprimos, ArrayList<Integer> lista_primos) {
int num;
for (int i=0; i<4; i++) {
System.out.println("Dame un numero: ");
num = sc.nextInt();
// Si es divisible por cualquiera de estos números, no
// es primo
if (num == 0 || num == 1 || num == 4)
lista_Noprimos.add(num);
System.out.println();
for (int x = 2; x < num / 2; x++) {
// Si es divisible por cualquiera de estos números, no
// es primo
if (num % x == 0)
lista_Noprimos.add(num);
//sino, es primo
else {
lista_primos.add(num);
}
}
}
return lista;
}
@Override
public void run() {
System.out.println("Arrancando hilo: "+ Thread.currentThread().getName());
try {
Thread.sleep(300);
}catch (InterruptedException e) {
e.printStackTrace();
}
sc.close();
System.out.println("El hilo ha terminado");
}
}
What I am not clear about is how to start the run() method using the objects created in the main method
The first thing you have to understand is that everything that is in threads can be executed at any time, and the fact of putting synchronized is equivalent to creating a bottleneck that is not really what you want in this case for the calculations but for data reading.
First we abstract the functionality of asking for numbers and returning a list, we will lose a bit of performance, but we will gain that your code is more reusable and easier to maintain.
Now we will use the threads to process the primes and non-primes in parallel, so we will rename your class as
ExtractorDePrimos
:As you will see, I reuse many of your ideas, such as:
Finally the main class to call everything remains as
It's important for you to know that threads don't necessarily end up in the order you created them, (and in fact that's why I print their name along with the results) so you might get output like the following.
In this run, if you notice, the calculations have been done independently, and thread 2 finished before thread one.
Although your example works, the code is very educational and seems to be written in your grandparents' time, since the already obsolete Java 8, new APIs have been added that allow us to do this code less in the object-oriented paradigm and a little more in the object-oriented paradigm. functional.
Since the order doesn't really matter to you, you can also do the calculation of esprimo in parallel with the use of the Stream API as follows:
note that
.parallel()
by itself it takes care of creating as manyThreads
as possible according to the limitations of your system for the code you pass to it.the call to
forEach()
is equivalent to an improved for , which internally uses an iterator instead of indices to traverse the list, and the parameter it receives is neither more nor less than a lambda function , which, as you can guess, allows us to greatly reduce the code that it would have been done in an anonymous inner class.The code looks better now, but it still has a lot of steps to be educational, and we're allocating an array the size of 4 integers for each list. We can modify it to use collectors and that alone in a parallel way classify the numbers
Now assuming he's a fan of the functional paradigm you could reduce your method to:
Although it is arranged very nicely, it only has two lines. To understand it, it is only necessary to observe that IntStream is a Stream but optimized for data of int types, and that the range method tries to generate numbers in a sequence from the initial value to the final value, then it simply gives us if for the given index the number in question is prime or not, and when chaining the method
findFirst
, the API internally optimizes the calls so that we don't have to generate the entire range that we initially specified for theIntStream
, but only until the condition is met. The last thing to note is that find first returns a semi-monad calledOptional
, although if you don't know how to use it you can generate NPE (no, it doesn't readnepe, that is how the NullPointerException is colloquially known), also when it is used intelligently as here it gives us values for the cases not contemplated, that is, for the cases in which it has not been marked as prime by the calculation, it is in charge of marking it as non-prime, and with that you save yourself from dealing with not-so-common types of numbers such as imaginary ones, negative ones, and other rare conditions that could take you out of the Z + space (read this final statement in a bombastic way).Some time ago I also created an article on how to generate series from a subset such as in this case the primes, and that you can find on my site with an explanation of some more things about the use of lambdas to make generators .