Blog
Las 56 preguntas y respuestas más frecuentes sobre Java
- Publicado por: Rafael Fernandez
- Categoría: Java
En este post vamos a cubrir una serie de preguntas importantes que te van a servir para una entrevista de Java, tanto para programadores nuevos como para los experimentados. Estas preguntas de entrevista están estructuradas para ayudarte a comprender los conceptos básicos sobre Java y para que le saques el máximo de provecho a tu entrevista y para que te familiarices con Java.
Java es un lenguaje de programación de alto nivel, multi-plataforma. Es una colección de objetos desarrollado por Sun Microsystems. Se usa en muchas aplicaciones, sitios web y juegos.
Características de Java:
- Polimorfismo
- Abstracción
- Herencia
- Encapsulacion
- Orientado a objetos
- Plataforma independiente: un programa funciona en diferentes plataformas sin necesidad de modificación.
- Alto rendimiento: JIT (compilador Just In Time) produce un alto rendimiento en Java. JIT convierte el bytecode en lenguaje de máquina y luego JVM inicia la ejecución.
- Hilo múltiple: se conoce como subproceso. JVM crea un hilo llamado hilo principal. El usuario puede crear varios subprocesos extendiendo la clase de subproceso o implementando la interfaz Runnable.
Usa el compilador Just In Time para permitir un alto rendimiento. Con JIT las instrucciones se convierten en códigos de bytes.
Los IDE de JAVA son: Eclipse y NetBeans
Los puntos a continuación explican en detalle lo que es un Constructor:
- Cuando se crea un nuevo objeto en un programa, se llama un constructor correspondiente a la clase.
- Es un método que tiene el mismo nombre que el nombre de la clase.
- Se puede crear un constructor implícitamente, o predeterminado.
- El constructor puede ser sobrecargado.
- El usuario puede crear un constructor con un parámetro, y crear otro constructor sin un parámetro.
Variable local: son las variables que han existido dentro del propio método.
Variable de instancia se define dentro de la clase y fuera del método y el alcance de las variables que existen en toda la clase
Una clase tiene variables y métodos y está integrada por códigos.
Las variables: son los atributos que definen el estado de una clase.
El método: es el lugar donde se debe hacer la lógica de negocios exacta. Contiene instrucciones (o), para satisfacer el requisito particular.
Ejemplo:
public class Addition{ //Class name declaration int a = 5; //Variable declaration int b= 5; public void add(){ //Method declaration int c = a+b; } }
Es una instancia de una clase. El objeto tiene estado y comportamiento.
Siempre que la JVM lea la palabra clave "new ()", creará una instancia de esa clase.
Ejemplo:
public class Addition{ public static void main(String[] args){ Addion add = new Addition();//Creacion de Objeto } }
El código anterior crea el objeto para la clase Addition.
Oops conceptos:
- Herencia
- Encapsulacion
- Polimorfismo
- Abstracción
- Interfaz
Herencia: indica que una clase puede extenderse a otra clase. De esta manera, los códigos puedan ser reutilizados de una clase a otra.
La clase que existe se conoce como Super clase, y la clase derivada como subclase.
Ejemplo:
Super class: public class Manupulation(){ } Sub class: public class Addition extends Manipulation(){ }
La herencia solo es aplicable para miembros públicos y protegidos, porque los privados no pueden ser heredados.
Propósito de encapsulación:
- Proteger el código de los demás.
- Mantener el código.
Ejemplo:
Estamos declarando 'a' como una variable entera y no debería ser negativa.
public class Addition(){ int a=5; }
Si alguien cambia la variable exacta como " a = -5", entonces es mala.
Pasos para superar el problema a continuación:
- hacer la variable como privada o protegida.
- Utilizar métodos de entrada público como set <property> y get <property>.
Para que el código anterior se pueda modificar como:
public class Addition(){ private int a = 5; //Aqui la variable se declara como privada }
El siguiente código muestra el getter y setter.
Se pueden suministrar condiciones al configurar la variable.
get A(){ } set A(int a){ if(a>0){// Se aplica la condición ......... } }
Para la encapsulación, se debe hacer que todas las variables de instancia sean privadas y crear un definidor y un captador para esas variables. Lo que a su vez obligará a otros a llamar a los configuradores en lugar de entrar directamente a los datos.
El Polimorfismo significa que tiene muchas formas.
Un solo objeto puede referirse a la superclase o subclase según el tipo de referencia que se denomine polimorfismo.
Ejemplo:
Public class Manipulation(){ //Super clase public void add(){ } } public class Addition extends Manipulation(){ // Sub clase public void add(){ } public static void main(String args[]){ Manipulation addition = new Addition();//Manipulation y Addition son el tipo de referencia addition.add(); } }
El polimorfismo se puede aplicar para anular y no para sobrecargar .
La anulación del método se produce si el método de subclase satisface las condiciones con el método de Super clase:
- El nombre del método debe ser el mismo
- El argumento debe ser igual
- Tipo de retorno también debe ser el mismo
El beneficio clave de la anulación es que la subclase puede suministrar cierta información específica sobre ese tipo de subclase que la súper clase.
Ejemplo:
public class Manipulation{ //Super clase public void add(){ ……………… } } Public class Addition extends Manipulation(){ Public void add(){ ……….. } Public static void main(String args[]){ Manipulation addition = new Addition(); //Se aplica el polimorfismo addition.add(); // Llama a la subclase add() method } }
El método addition.add() llama al método add() en la Subclase y no a la clase padre. Por lo tanto, anula el método de la Super clase se conoce como anulación (override) del método.
La sobrecarga de métodos se produce para diferentes clases o dentro de la misma clase, el método de subclase debe satisfacer las siguientes condiciones con los métodos de Super clase (o) en la misma clase:
- Mismo nombre de método
- Tipo de argumento diferente
- Puede tener distintos tipos de retorno
Ejemplo:
public class Manipulation{ //Super clase public void add(String name){ //parametro String ……………… } } Public class Addition extends Manipulation(){ Public void add(){//sin parametro ……….. } Public void add(int a){ //parametro entero } Public static void main(String args[]){ Addition addition = new Addition(); addition.add(); } }
Aquí, el método add() que tiene diferentes parámetros en la clase Addition está sobrecargado en la misma clase, así como con la súper clase.
Nota: el polimorfismo no se aplica para el método de overloading.
En Java no se puede lograr la herencia múltiple. Para corregir este problema se introduce el concepto de interfaz, que es una plantilla que tiene declaraciones de método, pero no la implementación del método.
Ejemplo:
Public abstract interface IManupulation{ //declaracion de la interfase Public abstract void add();//declaracion del metodo public abstract void subtract(); }
- Los métodos en la interfaz son internamente public abstract void.
- Las variables en la interfaz son internamente public static final.
- Las clases pueden implementar la interfaz y no se extienden.
- La clase que implementa la interfaz debe suministrar una implementación para los métodos declarados en la interfaz.
public class Manupulation implements IManupulation{ //Manupulation class uses the interface Public void add(){ …………… } Public void subtract(){ ……………. } }
Podemos crear la clase abstracta utilizando la palabra clave "abstracta " antes del nombre de la clase Una clase abstracta puede tener tanto métodos "abstractos" como métodos "no abstractos"que forman una clase concreta.
Ejemplo:
public abstract class Manupulation{ public abstract void add();//delaracion del metodo abstracto Public void subtract(){ } }
- La clase abstracta también puede tener un método no abstracto.
- La Subclase concreta que extiende la clase abstracta debe suministrar la implementación para los métodos abstractos.
La diferencia entre la Array y Array List se puede entender a partir de la siguiente tabla:
Array |
Array List |
El tamaño se da en el momento de la declaración de la matriz. String[] nombre = new String [2]. |
El tamaño puede no ser necesario. El tamaño cambia dinámicamente. ArrayList nombre = new ArrayList |
Para poner un objeto dentro del array hay que especificar el indice nombre [1] = "libro". |
No se necesita índice. nombre.add ("libro") |
Un array no es de tipo parametrizado. | Los ArrayList en java 5.0 están parametrizados. |
String (Cadena): Las variables de cadena se guardan en un "pool de strings constantes". Una vez que la referencia de string cambia el valor antiguo que existe en el "pool de strings constantes", no se puede borrar.
Ejemplo:
String nombre = "libro";
Pool de strings constantes
Si el valor del nombre ha cambiado de "libro" a "pluma".
Entonces, el valor más antiguo se mantiene en el pool de cadenas constantes.
Buffer de strings:
- Aquí los valores de strings se guardna en una pila. Al cambiar los valores, el nuevo valor sustituye al valor anterior.
- El buffer de strings se sincroniza, lo que es seguro para subprocesos.
- El rendimiento es más lento que el generador de strings.
Ejemplo:
String Buffer nombre= "libro";
Una vez que el valor del nombre se ha cambiado a "pluma", el "libro" se borra de la pila.
Constructor de strings: es lo mismo que el Buffer de strings, excepto el generador de strings, el cual no tiene seguridad de subprocesos y no está sincronizado. Lo que hace que su rendimiento sea rápido.
Los métodos y las variables de instancia son conocidos como miembros.
Públicos:
Los miembros públicos son visibles en el mismo paquete, así como en el paquete externo que es para los otros paquetes.
Los miembros públicos de la Clase A son visibles para la Clase B (mismo paquete), así como para la Clase C (Paquete diferente).
Privados:
Los miembros privados solo se ven en la misma clase y no para otras clases en el mismo paquete, así como las clases en los paquetes externos.
Los miembros privados en la clase A son visibles solo en esa clase. Es invisible tanto para la clase B como para la clase C.
Especificadores de acceso predeterminado: Son los métodos y las variables declaradas en una clase que no tienen especificador de acceso.
Los miembros predeterminados en la Clase A pueden ser vistos por las otras clases que están dentro del paquete, pero invisibles para las que están fuera del paquete.
Por tanto, los miembros de Clase A son visibles para Clase B e invisibles para Clase C.
Protegido:
Protegido es lo mismo que predeterminado, pero si una clase se extiende, entonces es visible incluso si está fuera del paquete.
Los miembros de Clase A son visibles para la Clase B porque está dentro del paquete. Para la Clase C es invisible, pero si la Clase C se extiende a la Clase A, los miembros son visibles para la Clase C, incluso si está fuera del paquete.
La diferencia entre HashMap y HashTable se puede ver a continuación:
HashMap | HashTable |
Los métodos no son sincronizados | Los métodos clave están sincronizados. |
No hay seguridad del hilo | Hay Seguridad del hilo |
El iterador se utiliza para iterar los valores. | El enumerador se usa para iterar los valores. |
Permite una clave nula y múltiples valores nulos. | No permite nada que sea nulo. |
El rendimiento es mas alto que HashTable |
El rendimiento es lento
|
Veamos la siguiente tabla:
HashSet | TreeSet |
Sus elementos insertados están en orden aleatorio. | Mantiene sus elementos en el orden ordenado. |
Puede guardar objetos nulos. | No se pudieron guardar objetos nulos. |
Su rendimiento es rápido. |
Su rendimiento es lento.
|
Clase abstracta:
- clase abstracta tiene un constructor predeterminado y se llama cada vez que se crea una instancia de la subclase concreta.
- Tiene métodos abstractos y no abstractos.
- La clase que extiende la clase abstracta no debería requerir la implementación de todos los métodos, solo los métodos abstractos deben implementarse en la subclase concreta.
- La clase abstracta tiene variables de instancia.
Interfaz:
- No tiene constructor y no puede ser instanciado.
- El método abstracto solo debe ser declarado.
- Las clases que implementan la interfaz deben suministrar la implementación de todos los métodos.
- La interfaz tiene solo constantes.
Collection: significa marco diseñado para guardar los objetos y manipular el diseño para almacenar los objetos.
Las colecciones son utilizadas para realizar operaciones como:
- Manipulación
- Clasificación
- buscando
- Supresión
- Inserción
Las colecciones son grupos de objetos, las clases e interfaces para recopilar están disponibles en el paquete 'utile' de Java.
Clases e interfaces disponibles en las colecciones:
Interfaces:
- Collection (Colección)
- List (Lista)
- Map (Mapa)
- Sorted Set (Conjunto)
- Sorted map (Conjunto ordenado)
- Queue (Cola)
Classes:
- Lists
- Array List
- Vector
- Linked List
Sets:
- Hash set
- Linked Hash Set
- Tree Set
Maps:
- Hash Map
- Hash Table
- Tree Map
- Linked Hashed Map
Queue:
- Priority Queue
Ordenado:
Significa que los valores que se guardan en una colección están basados en los valores que se agregan a la colección. Entonces podemos iterar los valores de la colección en un orden específico.
Arreglado en colecciones:
El mecanismo empleado para la clasificación puede aplicarse interna o externamente para que el grupo de objetos ordenados en una colección particular se base en las propiedades de los objetos.
Los valores que son agregados a la lista se basan en la posición del índice y están ordenados por la posición del índice. Se permiten duplicados.
Tipos de listas son:
Array List:
- Rápida iteración y acceso aleatorio.
- Colección ordenada (por índice) y no ordenada.
- Maneja interfaz de acceso aleatorio.
Ejemplo:
public class frutas{ public static void main (String [ ] args){ ArrayList <String>nombres=new ArrayList <String>(); names.add (“manzana”); names.add (“cereza”); names.add (“kiwi”); names.add (“platano”); names.add (“cereza”); System.out.println (nombres); } }
Salida:
[Manzana, cereza, kiwi, platano, cereza]Desde la salida, el Array List mantiene el orden de inserción y acepta los duplicados pero no ordenados.
Vector:
Es lo mismo que el Array List.
- Métodos vectoriales sincronizados.
- Hilo de seguridad.
- implementa el acceso aleatorio.
- La seguridad del hilo generalmente causa un impacto en el rendimiento.
Ejemplo:
public class frutas{ public static void main (String [ ] args){ Vector <String> nombres = new Vector <String> ( ); names.add (“cereza”); names.add (“manzana”); names.add (“platano”); names.add (“kiwi”); names.add (“manzana”); System.out.println (“nombres”); } }
Salida:
[Cereza, manzana, plátano, kiwi, manzana]Vector también mantiene el orden de inserción y acepta los duplicados.
Linked List:
- Los elementos están doblemente vinculados entre sí.
- El rendimiento es lento que el Array list.
- Buena elección para inserción y eliminación.
- Java 5.0 es compatible con los métodos comunes de cola como peek (), Pool (), Offer () etc.
Ejemplo:
public class frutas{ public static void main (String [ ] args){ Linkedlist <String> nombres= new linkedlist <String> ( ) ; names.add(“platano”); names.add(“cereza”); names.add(“manzana”); names.add(“kiwi”); names.add(“platano”); System.out.println (names); } }
Salida:
[platano, cereza, manzana, kiwi, platano]Mantiene el orden de inserción y acepta los duplicados.
No permite duplicaciones. En este caso, el método "equals ()" se usa para determinar si dos objetos son idénticos o no.
Hash Set:
- Desordenado y sin clasificar.
- Usa el código hash del objeto para insertar los valores.
- Use esto cuando el requisito sea "sin duplicados y no importa el pedido".
Ejemplo:
public class frutas{ public static void main (String[ ] args){ HashSet<String> nombres= new HashSet <=String>( ) ; names.add(“platano”); names.add(“cereza”); names.add(“manzana”); names.add(“kiwi”); names.add(“platano”); System.out.println (names); } }
Salida:
[plátano, cereza, kiwi, manzana]No sigue ningún orden de inserción. No se permiten duplicados.
Conjunto de hash vinculado:
- Una versión ordenada del conjunto hash es conocida como conjunto hash vinculado.
- Mantiene una lista doblemente enlazada de todos los elementos.
- Se usa esto cuando se requiera la orden de iteración.
Ejemplo:
public class frutas{ public static void main (String[ ] args){ LinkedHashSet<String> nombres= new LinkedHashSet <String>( ) ; names.add(“platano”); names.add(“cereza”); names.add(“manzana”); names.add(“kiwi”); names.add(“platano”); System.out.println (names); } }
Salida:
[platano, cereza, manzana, kiwi]Mantiene el orden de inserción en el que se han agregado al conjunto. No se permiten duplicados.
Tree Set
- Es una de las dos colecciones ordenadas.
- Utiliza la estructura de "Read-Black" y garantiza que los elementos estarán en orden ascendente.
- Podemos construir un tree set con el constructor usando un comparador (or).
Ejemplo:
public class frutas{ public static void main (String[ ]args) { Treeset<String> nombres= new TreeSet<String>( ) ; names.add(“cereza”); names.add(“platano”); names.add(“manzana”); names.add(“kiwi”); names.add(“cereza”); System.out.println(nombres); } }
Salida:
[cereza, kiwi, manzana, plátano,]TreeSet ordena los elementos en orden ascendente y los duplicados no están permitidos.
Map se preocupa por el identificador único. Podemos mapear una clave única a un valor específico. Es un par clave / valor. Podemos buscar un valor, en función de la clave. Al igual que el set, map también usa el método "equals ()" para determinar si dos teclas son iguales o diferentes.
Hash Map:
- Mapa desordenado y sin clasificar.
- Hashmap es una buena opción cuando no nos importa el orden.
- Permite una clave nula y múltiples valores nulos.
Ejemplo:
Public class frutas{ Public static void main(String[ ] args){ HashMap<Sting,String> nombres=new HashMap<String,String>( ); names.put(“clave1”,“cereza”); names.put (“clave2”,“platano”); names.put (“clave3”,“manzana”); names.put (“clave4”,“kiwi”); names.put (“clave1”,“cereza”); System.out.println(names); } }
Salida:
{clave2= platano, clave1= cereza, clave4= kiwi, clave3= manzana}
No se permiten claves duplicadas en el mapa.
No mantiene ningún orden de inserción y está sin clasificar.
Hash Table:
- Como vector clave, los métodos de la clase están sincronizados.
- Hilo seguro y disminuye el rendimiento.
- No permite nada que sea nulo.
Ejemplo:
public class frutas{ public static void main(String[ ]args){ Hashtable<Sting,String> nombres=new Hashtable<String,String>( ); names.put(“clave1”,“cereza”); names.put(“clave2”,“manzana”); names.put(“clave3”,“platano”); names.put(“clave4”,“kiwi”); names.put(“clave2”,“naranja”); System.out.println(nombres); } }
Salida:
{clave2= manzana, clave1 = cereza, clave4= kiwi, clave3= banana}
No se permiten claves duplicadas.
Linked Hash Map:
- Mantiene el orden de inserción.
- Es más lento que el Hash Map
- Se espera una iteración más rápida.
Ejemplo:
public class frutas{ public static void main(String[ ] args){ LinkedHashMap<Sting,String> nombres=new LinkedHashMap<String,String>( ); names.put(“clave1”,“cereza”); names.put(“clave2”,“manazana”); names.put(“clave3”,“platano”); names.put(“clave4”,“kiwi”); names.put(“clave2”,“naranja”); System.out.println(nombres); } }
Salida:
{clave2= manzana, clave1 = cereza, clave4 = kiwi, clave3 = platano}
No se permiten claves duplicadas.
TreeMap:
- Mapa ordenado
- Al igual que Tree set, se puede construir un orden de clasificación con el constructor.
Ejemplo:
public class frutas{ public static void main(String[ ]args){ TreeMap<Sting,String> nombres=new TreeMap<String,String>( ); names.put(“clave1”,“cereza”); names.put(“clave2”,“platano”); names.put(“clave3”,“manzana”); names.put(“clave4”,“kiwi”); names.put(“clave2”,“naranja”); System.out.println(nombres); } }
Salida:
{clave1 = cereza, clave2 = platano, clave3 = manzana, clave4 = kiwi}
Se ordena en orden ascendente en función de la clave. No permite claves duplicadas.
Interfaz de cola
Cola de prioridad: Linked list class ha sido mejorada para implementar la interfaz de cola. Las colas se pueden trabajar con una linked list. El propósito de una cola es "Prioridad de entrada, Prioridad de salida".
Por tanto, los elementos son ordenados de forma natural o según el comparador. El orden de los elementos representa su prioridad relativa.
La excepción es un problema que puede ocasionarse durante el flujo normal de una ejecución. Un método puede lanzar una excepción cuando algo se detecta en el tiempo de la ejecución. Si la excepción no se puede manejar, entonces la ejecución termina antes de completar la tarea. En cambio, si se maneja la excepción entonces el flujo normal se continua. Las excepciones son una subclase de java.lang.Exception.
Ejemplo para el manejo de excepciones:
try{ //Los codigos riesgosos (Risky) se ponen en este bloque }catch(Exception e){ //Las excepciones se colocan en el bloque catch. }
Son Dos tipos de excepciones:
Checked Exception:
En esta el compilador verifica estas excepciones en el momento de la compilación. Las clases que extienden la clase Throwable excepto Runtime exception y Error se llaman excepción comprobada (checked exception)
Entonces toda excepción comprobada debe declarar la excepción mediante la palabra clave throes (o) rodeada por un try / catch apropiado.
Ejemplo: ClassNotFound Exception
Unchecked Exception:
Estas compilaciones no comprueban las excepciones durante la compilación. El compilador no obliga a manejar estas excepciones.
Incluye:
- Excepción aritmética
- Excepción ArrayIndexOutOfBounds
Dos maneras diferentes de manejar las excepciones:
# 1) Usando try / catch:
Un código de riesgo (risky code) está rodeado por un bloque try. Si ocurre una excepción, entonces es atrapado por el bloque catch que es seguido por el bloque try.
Ejemplo:
class Manipulation{ public static void main(String[] args){ add(); } Public void add(){ try{ addition(); }catch(Exception e){ e.printStacktrace(); } } }
# 2) Al declarar throws keyword:
Al final del método, podemos declarar la excepción mediante la palabra clave throws.
Ejemplo:
class Manipulation{ public static void main(String[] args){ add(); } public void add() throws Exception{ addition(); } }
Ventajas:
- El flujo normal de la ejecución no culmina si se maneja la excepción
- Se puede identificar el problema utilizando la declaración de captura
Las palabras clave de manejo de excepciones:
try:
Cuando un código de riesgo está rodeado por un bloque try. Una excepción que ocurre en el bloque try es capturada por un bloque catch. La prueba puede ser seguida por la captura (o) finalmente (o) ambas. Pero cualquiera de los bloques es obligatorio.
catch:
A esto le sigue el bloque try. Las excepciones son atrapadas aquí.
finally:
A esto le sigue el bloque try (o) catch. Este bloque se ejecuta independientemente de una excepción. Así que generalmente se proporcionan códigos de limpieza aquí.
La excepción es lanzada primero desde el método que ocupa la parte superior de la pila. Si no se detecta, aparece el método y se mueve al método anterior y así sucesivamente hasta que se obtienen.
Esto se llama propagación de excepciones.
Ejemplo:
public class Manipulation{ public static void main(String[] args){ add(); } public void add(){ addition(); }
Del ejemplo anterior, la pila se ve como se muestra a continuación:
addition()
add()
main()
Si una excepción se produjo en addition() el método no es capturado, entonces se mueve al método add (). Luego se mueve al método main () y luego detiene el flujo de ejecución. A esto se le llama propagación de excepciones.
Final variable:
Una vez declara como final la variable, el valor de la variable no se pudo cambiar. Es como una constante.
Ejemplo:
final int = 12;
Final method:
Una palabra clave final en un método que no se puede anular. Si un método se marca como final, la subclase no puede anularlo.
Final Class:
Si una clase se declara como final, ya no puede ser subclasificada. Ya que ninguna clase puede extender la clase final.
Cada programa java tiene por lo menos un hilo llamado hilo principal, el cual es creado por JVM. El usuario puede definir sus propios hilos extendiendo la clase Thread (o) implementando la interfaz Runnable. Los hilos se ejecutan al mismo tiempo.
Ejemplo:
public static void main(String[] args){//main thread starts here }
Hay dos formas para hacer un hilo.
# 1) Extender la clase Thread:
Extender una clase Thread y anular el método de ejecución. El hilo está disponible en java.lang.thread.
Ejemplo:
Public class Addition extends Thread { public void run () { } }
Una desventaja de usar una clase de subproceso es que no se puede extender ninguna otra clase porque ya se ha extendido la clase de subproceso. Pero se puede sobrecargar el método run () en nuestra clase.
# 2) Implementar la interfaz de Runnable:
Otra forma es implementando la interfaz runnable. Para ello, se debe suministrar la implementación del método run () que es definido en la interfaz.
Ejemplo:
Public class Addition implements Runnable { public void run () { } }
El método Join () es utilizado para unir un hilo con el final del hilo que se está ejecutando actualmente.
Ejemplo:
public static void main (String[] args){ Thread t = new Thread (); t.start (); t.join (); }
A partir del código anterior, el hilo principal comenzó la ejecución. Cuando llega al código t.start () , 'thread t' inicia la propia pila para la ejecución. JVM cambia entre el hilo principal y el 'hilo t'.
Una vez que alcanza el código t.join () , se ejecuta 'thread t' solo, y completa su tarea, luego solo el hilo principal comenzó la ejecución. No es un método estático.
Un método yield () mueve el hilo que está en ejecución a un estado ejecutable y permite que se ejecuten los otros hilos para que los hilos de igual prioridad tengan la oportunidad de ejecutarse. Es un método estático. No libera ningún bloqueo.
El método yield () mueve el subproceso de vuelta al estado Ejecutable (runnable) solamente, y no el hilo a sleep(), wait () (o).
Ejemplo:
public static void main (String[] args){ Thread t = new Thread (); t.start (); } public void run(){ Thread.yield(); } }
El método wait () se usa para hacer que el hilo espere en el grupo de espera. Cuando se ejecuta un método wait () durante la ejecución de un subproceso inmediatamente el subproceso deja el bloqueo del objeto y se va al grupo de espera. El método wait () le dice al hilo que espere por un tiempo determinado.
Luego, el hilo se activará después de que se llame al método de notificación () (o) notificación a todos (). Wait () y los otros métodos nombrados anteriormente no dan el bloqueo en el objeto de forma inmediata, hasta que el hilo que se está ejecutando actualmente complete el código sincronizado. Se usa principalmente en la sincronización.
Ejemplo:
public static void main (String[] args){ Thread t = new Thread (); t.start (); Synchronized (t) { Wait(); } }
Básicamente se trata de lo siguiente:
notify() | nofityAll() |
Este método se usa para enviar una señal y activar un hilo en el grupo de espera. | Este método manda la señal para activar todos los hilos en un carrete de espera (waiting spool). |
Se puede detener un hilo usando los siguientes métodos de hilo.
- sleeping
- waiting
- blocked
Sleep:
El método Sleep () se usa para dormir el subproceso que se está ejecutando actualmente durante el tiempo especificado. Una vez que el hilo está activo, puede moverse al estado ejecutable. Por tanto, el método sleep () se usa para retardar la ejecución durante algún período. Es un método estático.
Ejemplo:
Thread. Sleep (2000)
Por lo que, retarda el hilo para dormir 2 milisegundos. El método Sleep () lanza una excepción ininterrumpida, por lo tanto, se necesita rodear el bloque con try / catch.
public class ExampleThread implements Runnable{ public static void main (String[] args){ Thread t = new Thread (); t.start (); } public void run(){ try{ Thread.sleep(2000); }catch(InterruptedException e){ } }
Podemos usar la interfaz runnable, si se necesita que nuestra clase extienda algunas otras clases además del hilo porque en Java solo podemos extender una clase.
Si no se va a extender ninguna clase, entonces se puede extender la clase thread.
El método Start () crea un nuevo hilo y el código dentro del método run () se ejecuta en el nuevo hilo. Si se llama en forma directa al método run (), entonces, no se creará un nuevo hilo y el hilo que se está ejecutando continua ejecutando el método run ().
Significa que muchos hilos se ejecutan en forma simultánea. Cada subproceso inicia su propia pila en función de la prioridad de flujo (o) de los subprocesos.
Programa de ejemplo:
public class MultipleThreads implements Runnable { public static void main (String[] args){//Hilo principal comienza aqui Runnable r = new runnable (); Thread t=new thread (); t.start ();//El hilo del usuario comienza aqui Addition add=new addition (); } public void run(){ go(); }//El hilo del usuario termina aqui }
En la ejecución de la primera línea, JVM llama al método principal. Una vez que la ejecución alcanza la línea t.start (), se crea un nuevo hilo y también se crea la nueva pila para el hilo. Ahora JVM cambia al nuevo hilo y el hilo principal vuelve al estado ejecutable. JVM cambia entre cada hilo hasta que ambos hilos se completan. A esto se le llama multi-threading.
Los hilos o threads tienen los siguientes estados:
- new
- runnable
- running
- non-runnable (blocked)
- Terminated
New:
En el estado New, la instancia de Thread se ha creado pero el método start () aún no se ha invocado. Por ahora el hilo no se considera vivo.
Runnable:
En el estado ejecutable se encuentra el subproceso después de la llamada del método start () pero antes de que se invoque el método run (). Pero un hilo también puede volver al estado ejecutable desde esperar / dormir. En este estado el hilo se considera vivo.
Running:
El subproceso está en estado de ejecución después de que llama al método run (). Ahora el hilo comienza la ejecución.
Non-runnable (blocked)
El hilo está vivo pero no es elegible para ejecutarse, pero también volverá al estado ejecutable después de algún tiempo.
Ejemplo: wait, sleep, block.
Terminated:
Una vez que se completa el método de ejecución, se termina. Ahora el hilo no está vivo.
La sincronización hace que un solo hilo entre a un bloque de código a la vez. Si varios subprocesos acceden al bloque de código se da la posibilidad de lograr resultados inexactos al final. Para evitar este problema, podemos suministrar sincronización para el bloque de códigos confidenciales.
La palabra clave synchronized, significa que un hilo necesita una clave para entrar al código sincronizado.
Las cerraduras son por objetos. Cada objeto en Java tiene un bloqueo. Una cerradura con una sola llave. Un hilo puede entar a un método sincronizado, solo si el hilo puede obtener la clave para el bloqueo de objetos. Para ello, utilizamos la palabra clave "Synchronized".
Ejemplo:
public class ExampleThread implements Runnable{ public static void main (String[] args){ Thread t = new Thread (); t.start (); } public void run(){ synchronized(object){ { } }
La sincronización para implementar todos los métodos, no es recomendada. Esto es porque si un hilo entra al código sincronizado, entonces el siguiente hilo debería tener que esperar, lo que hace lento el rendimiento en el otro extremo.
La serialización es la conversión de un archivo en un flujo de bytes. Los objetos en el archivo se convierten a los bytes por motivos de seguridad. Para esto, se necesita implementar la interfaz java.io.Serializable. No tiene método para definir.
Las variables marcadas como transitorias no forman parte de la serialización. Por lo tanto, podemos omitir la serialización de las variables en el archivo usando una palabra clave transitoria.
Las variables transitorias no son parte del proceso de serialización. Mientras se produce este proceso, los valores de las variables transitorias se establecen en el valor predeterminado. No se usa con variables estáticas.
Ejemplo:
transient int numbers;
Las clases ObjectOutputStream y ObjectInputStream son de nivel superior java.io.package. Los utilizaremos con las clases de nivel inferior FileOutputStream y FileInputStream.
ObjectOutputStream.writeObject —-> Serializar el objeto y escribir el objeto serializado en un archivo.
ObjectInputStream.readObject -> Lee el archivo y deserializa el objeto.
Para ser serializado, un objeto debe implementar la interfaz serializable. Si la superclase implementa Serializable, entonces la subclase será serializable.
Los valores variables volátiles siempre se leen desde la memoria principal y no desde la caché del hilo. Esto se usa durante la sincronización. Es aplicable solo para variables.
Ejemplo:
volatile int number;
Serialization | Deserialization |
La serialización es el proceso que se usa para convertir los objetos en un flujo de bytes. | La deserialización un proceso opuesto a la serialización donde se puede recuperar los objetos del flujo de bytes. |
Un objeto se serializa escribiéndolo en un ObjectOutputStream. | Un objeto se deserializa al leerlo desde un ObjectInputStream. |
Al serializar un objeto, este se estampa con un número de ID de versión para la clase de objeto. Este ID se llama SerialVersionUID y se usa durante la deserialización para verificar que el remitente y el receptor sean compatibles con la serialización.