Use Wait () y notify () para lograr la colaboración entre subcontratación
1. Wait () y notify ()/notifyall ()
Cuando se llaman Sleep () y el rendimiento (), el bloqueo no se libera, y llamar a Wait () liberará el bloqueo. De esta manera, otra tarea (hilo) puede obtener el bloqueo del objeto actual, ingresando así su método sincronizado. Puede reanudar la ejecución de Wait () a través de notify ()/notifyall () o el tiempo expira.
Wait (), notify () y notifyall () solo se puede llamar en el método de control de sincronización o el bloque de sincronización. Si estos métodos se llaman en un método asincrónico, una excepción ilegalmonitorStateException se lanzará en tiempo de ejecución.
2. Simule la activación de múltiples hilos por un solo hilo
Simular la colaboración entre hilos. La clase de juego tiene 2 métodos de sincronización Prepare () y Go (). El inicio del indicador se usa para determinar si el hilo actual necesita esperar (). La instancia de la clase de juego comienza a todas las instancias de clase Athele primero e ingresa el estado Wait (). Después de un período de tiempo, cambie el bit de bandera y notifyall () todos los hilos de Athele en el estado de espera.
Game.java
concurrencia de paquete; import java.util.collection; import java.util.collections; import java.util.hashset; import java.util.iterator; import java.util.set; clase atleta implementa runnable {private final int id; juego privado; Public Athlete (int id, juego) {this.id = id; this.game = juego; } public boolean iguales (objeto o) {if (! (o instancia de atleta)) return false; Atleta atleta = (atleta) o; ID de retorno == Atlete.id; } public string toString () {return "atlete <" + id + ">"; } public int hashcode () {return new Integer (id) .hashCode (); } public void run () {try {game.prepare (this); } catch (InterruptedException e) {System.out.println (this + "abandona el juego"); }}} El juego de clase pública implementa runnable {private set <thlete> jugadores = new Hashset <thlete> (); inicio booleano privado = falso; public void addplayer (atleta uno) {jugadores.add (uno); } public void removePlayer (atleta uno) {jugadores.remove (uno); } colección pública <thlete> getPlayers () {return Collections.unmodifiAbleset (jugadores); } public void prepare (atleta atleta) arroja interruptedException {System.out.println (atleta + "listo!"); sincronizado (this) {while (! start) wait (); if (start) system.out.println (atleta + "¡ir!"); }} public sincronizado void go () {notifyAll (); } public void Ready () {Iterator <thlete> iter = getPlayers (). iterator (); while (iter.hasnext ()) nuevo hilo (iter.next ()). start (); } public void run () {start = false; System.out.println ("listo ..."); System.out.println ("listo ..."); System.out.println ("listo ..."); listo(); inicio = verdadero; System.out.println ("¡GO!"); ir(); } public static void main (string [] args) {juego juego = new Game (); para (int i = 0; i <10; i ++) game.addplayer (nuevo atleta (i, juego)); nuevo hilo (juego) .Start (); }} resultado:
Listo ... listo ... listo ... atleta <0> listo! Atleta <1> listo! Atleta <2> listo! Atleta <3> listo! Atleta <4> listo! Atleta <5> listo! Atlete <6> listo! Atleta <7> listo! Atlete <8> listo! Atlete <9> listo! Go! Atlete <9> go! Atlete <8> go! Atlete <8> listos! Atlete <9> listos! Go! Athlete <9> Go! Atlete <8> Go! Athlete de Atlete <8> ¡Listo! Atlete! GO! Atleta <5> GO! Atleta <4> ¡GO! ATLETO <3> GO! ATLETO <2> GO! ATLETO <1> GO! ATLETO <0> ¡GO!
3. Simule el proceso de espera ocupado
Una instancia de la clase MyObject es el observador. Cuando ocurre un evento de observación, notificará a una instancia de la clase de monitor (la forma en que es cambiar un indicador). La instancia de esta clase de monitor verifica constantemente si el bit de bandera cambia esperando.
Ocupado sija.java
import java.util.concurrent.timeunit; class myObject implements runnable {private monitor monitor; public myObject (monitor monitor) {this.monitor = monitor; } public void run () {try {timeUnit.seconds.sleep (3); System.out.println ("Voy"); monitor.gotMessage (); } catch (InterruptedException e) {E.PrintStackTrace (); }}} El monitor de clase implementa runnable {private volátil boolean go = false; public void gotMessage () lanza interruptedException {go = true; } public void watch () {while (go == false); System.out.println ("Se ha ido"); } public void run () {watch (); }} clase pública ocupada que pasa {public static void main (string [] args) {monitor monitor = new Monitor (); MyObject o = nuevo MyObject (monitor); nuevo hilo (O) .Start (); nuevo hilo (monitor) .Start (); }} resultado:
Me voy. Se ha ido.
4. Use Wait () y notify () para reescribir el ejemplo anterior
El siguiente ejemplo reemplaza el mecanismo de espera ocupado a través de Wait (). Cuando se recibe un mensaje de notificación, notifique al hilo de la clase de monitor actual.
Esperar.java
paquete concurrencia.wait; import java.util.concurrent.timeunit; class myObject implements runnable {private monitor monitor; public myObject (monitor monitor) {this.monitor = monitor; } Comience el hilo regularmente
Aquí hay dos formas de iniciar un hilo después de un tiempo específico. Primero, se implementa a través de java.util.concurrent.delayqueue; En segundo lugar, se implementa a través de java.util.concurrent.scheduledthreadpoolexecutor.
1. Java.util.concurrent.delayqueue
La clase de retraso es una cola de bloqueo ilimitada de la cual los elementos se pueden extraer solo cuando expira el retraso. Acepta instancias que implementan la interfaz retrasada como elementos.
<< interfaz >> retrasado.java
paquete java.util.concurrent; import java.util.*; interfaz pública retrasada extiende comparable <detraso> {long getDelay (unidad de tiempo de tiempo);}getDelay () devuelve el tiempo de retraso restante asociado con este objeto, expresado en unidades de tiempo dadas. La implementación de esta interfaz debe definir un método Compareto que proporcione un tipo consistente con el método GetDelay de esta interfaz.
El jefe de la cola de retraso de Delayqueue es el elemento retrasado con el tiempo de almacenamiento más largo después de que expira el retraso. La expiración ocurre cuando el método GetDelay (TimeUnit.nanosegundos) de un elemento devuelve un valor inferior o igual a 0.
2. Colas de diseño con características de retraso de tiempo
La clase DelteredTasker mantiene una cola de Delayqueue <SardedTask>, donde la tarta de retraso implementa la interfaz retrasada y está definida por una clase interna. Tanto las clases externas como las clases internas implementan la interfaz ejecutable. Para las clases externas, su método de ejecución saca tareas en la cola en secuencia de acuerdo con el tiempo definido, y estas tareas son instancias de clases internas. El método Ejecutar de clases internas define la lógica específica de cada hilo.
La esencia de este diseño es definir una lista de tareas de hilos con las características de tiempo, y la lista puede ser de longitud. Especifique el tiempo de inicio cada vez que agrega una tarea.
DeletedTasker.java
paquete com.zj.timedTask; import static java.util.concurrent.timeunit.seconds; import static java.util.concurrent.timeunit.nanoseConds; import java.util.collection; import java.util.collections; import java.util.collections; importación; java.util.concurrent.delayed; import java.util.concurrent.executorservice; import java.util.concurrent.executors; import java.util.concurrent.timeUnit; clase pública retrasada implementa runnable {demandarqueue <retrasoTask> Queue = newayqueue <Newayqueue <DeletedTask () () (); public void addTask (DelayedTask e) {queue.put (e); } public void RemoveTask () {queue.poll (); } colección pública <LetreDedTask> getAllTasks () {return Collections.unmodifiablecollection (cola); } public int getTaskQuantity () {return queue.size (); } public void run () {while (! queue.isEmpty ()) try {queue.take (). run (); } capt (interruptedException e) {System.out.println ("interrumpido"); } System.out.println ("terminado DeletedTask"); } clase pública de clase estática DelteredTask implementa retrasada, ejecutable {private static int contador = 0; Private final int id = contador ++; Private final int delta; Disparador largo de Long Private; Public DeletedTask (int demoraConds) {delta = retrasoinSeconds; trigger = system.nanotime () + nanoseConds.convert (delta, segundos); } public Long getDelay (unidad de tiempo de tiempo) {return unit.convert (disparador - system.nanotime (), nanosegundos); } public int Compareto (retrasado arg) {demandarTastek that = (demandarTastask) arg; if (trigger <that.trigger) return -1; if (trigger> that.trigger) return 1; regresar 0; } public void run () {// Ejecute todo lo que desea hacer System.out.println (esto); } public String toString () {return "[" + delta + "s]" + "tarea" + id; }} public static void main (string [] args) {random rand = new Random (); EjecutorService exec = Ejecutors.NewCachedThreadPool (); DeletedTasker Tasker = new DardedTasker (); para (int i = 0; i <10; i ++) tasker.addtask (new DeletedTask (rand.nextint (5))); exec.Execute (Tasker); exec.shutdown (); }} resultado:
[0s] Tarea 1 [0s] Tarea 2 [0s] Tarea 3 [1S] Tarea 6 [2s] Tarea 5 [3s] Tarea 8 [4S] Tarea 0 [4S] Tarea 4 [4S] Tarea 7 [4S] Tarea 9 FinishedDelayTtask
3. Java.util.concurrent.scheduledThreadPoolExecutor
Esta clase se puede programar para ejecutar tareas (hilos) después de un retraso determinado, o realizar tareas regularmente (repetir). En el constructor, debe saber el tamaño del grupo de hilos. El método principal es:
[1] Programa
Public ProchuledFuture <?> Anexo (comando ejecutable, retraso largo, unidad de tiempo de tiempo)
Crea y realiza una operación única habilitada después de un retraso dado.
Designado por:
- Programe en la interfaz ProgramedExecutorService;
parámetro:
-Command: la tarea a realizar;
-delay: el tiempo para retrasar la ejecución a partir de ahora;
-unidad - la unidad de tiempo de los parámetros de retraso;
devolver:
- Indica lafuture programado que suspende la tarea y su método get () devolverá nulo después de la finalización.
[2] ScheduleAtFixedRate
Public ProchuledFuture <?> scheduleatFixedRate (
Comando ejecutable, larga inicialdelay, período largo, unidad de tiempo de tiempo)
Cree y ejecute una operación periódica que primero se habilite después de un retraso inicial dado, con operaciones posteriores que tienen un período determinado; Es decir, comenzará después de InitialDelay, luego después del período InitialDelay +, luego después del período InitialDelay + 2 *, y así sucesivamente. Si alguna ejecución de una tarea encuentra una excepción, se cancelará la ejecución posterior. De lo contrario, la tarea solo se puede finalizar ejecutando el método de cancelación o terminación del programa. Si alguna de las ejecuciones de esta tarea lleva más tiempo que su ciclo, la ejecución posterior se pospondrá, pero no simultáneamente.
Designado por:
- ScheduleAtFixedRate in Interface ScheduledExecutorService;
parámetro:
-Command: la tarea a realizar;
-InitialDelay: el tiempo de retraso para la primera ejecución;
-Pario: el período entre ejecuciones continuas;
-unidad - la unidad de tiempo de InitialDelay y parámetros de período;
devolver:
- Indica que se completa lafuture programado de la tarea suspendida, y su método get () lanzará una excepción después de que se cancele.
4. Diseñe los ejecutores de hilos con características de retraso de tiempo
La clase ScheduletAded Associats A ScheduledThreadPoolExcutor, que puede especificar el tamaño del grupo de subprocesos. Conozca el hilo y el tiempo de retraso a través del método de programación y cierre el grupo de hilo a través del método de cierre. La lógica de tareas específicas (hilos) tiene cierta flexibilidad (en comparación con el diseño anterior, el diseño anterior debe definir la lógica del hilo por adelantado, pero el diseño lógico específico del hilo puede modificarse por herencia o decoración).
Scheduletasker.java
paquete com.zj.timedtask; import java.util.concurrent.scheduledThreadPoolExecutor; import java.util.concurrent.timeunit; public class scheduletasker {private int corePoolSize = 10; ProchuledThreadPoolExecutor Scheduler; public ScheduleTasker () {Scheduler = new ScheduledThreadPoolExecutor (corePoolSize); } public ScheduleTasker (int Cantidad) {corePoolSize = cantidad; Scheduler = new ScheduledThreadPoolExecutor (corePoolSize); } horario público nulo (evento runnable, retraso largo) {scheduler.schedule (evento, demora, timeunit.seconds); } public void shutdown () {scheduler.shutdown (); } public static void main (string [] args) {scheduleTasker tasker = new ScheduleTasker (); tasker.schedule (new runnable () {public void run () {system.out.println ("[1s] tarea 1");}}, 1); tasker.schedule (new runnable () {public void run () {system.out.println ("[2s] tarea 2");}}, 2); tasker.schedule (new runnable () {public void run () {System.out.println ("[4S] Tarea 3");}}, 4); tasker.schedule (new runnable () {public void run () {public void run () {system.out.println ("[10s] tarea 4");}, 10); Tasker.shutdown (); }} resultado:
[1S] Tarea 1 [2s] Tarea 2 [4S] Tarea 3 [10s] Tarea 4 public void run () {try {timeUnit.seconds.sleep (3); System.out.println ("Voy"); monitor.gotMessage (); } catch (InterruptedException e) {E.PrintStackTrace (); }}} Class Monitor implementa Runnable {private volátil boolean go = false; public sincronizado void gotMessage () lanza interruptedException {go = true; notificar(); } public sincronizado void watch () lanza interruptedException {while (go == false) espera (); System.out.println ("Se ha ido"); } public void run () {try {watch (); } catch (InterruptedException e) {E.PrintStackTrace (); }}} public class Wait {public static void main (string [] args) {monitor monitor = nuevo monitor (); MyObject o = nuevo MyObject (monitor); nuevo hilo (O) .Start (); nuevo hilo (monitor) .Start (); }} resultado:
Me voy. Se ha ido.