visual vertical uiswing tutorial setborder layouts javase fillers docs crear con borde java multithreading concurrency

java - vertical - Cómo implementar un subprocesamiento simple con un número fijo de subprocesos de trabajo



swing fillers java (7)

/* Get an executor service that will run a maximum of 5 threads at a time: */ ExecutorService exec = Executors.newFixedThreadPool(5); /* For all the 100 tasks to be done altogether... */ for (int i = 0; i < 100; i++) { /* ...execute the task to run concurrently as a runnable: */ exec.execute(new Runnable() { public void run() { /* do the work to be done in its own thread */ System.out.println("Running in: " + Thread.currentThread()); } }); } /* Tell the executor that after these 100 steps above, we will be done: */ exec.shutdown(); try { /* The tasks are now running concurrently. We wait until all work is done, * with a timeout of 50 seconds: */ boolean b = exec.awaitTermination(50, TimeUnit.SECONDS); /* If the execution timed out, false is returned: */ System.out.println("All done: " + b); } catch (InterruptedException e) { e.printStackTrace(); }

Estoy buscando la forma más sencilla y directa de implementar lo siguiente:

  • El programa principal crea instancias de hilos de trabajo para realizar una tarea.
  • Solo se pueden ejecutar n tareas a la vez.
  • Cuando se llega a n , no se inician más trabajadores hasta que el recuento de subprocesos en ejecución cae por debajo de n .

Si quieres hacer tu propio:

private static final int MAX_WORKERS = n; private List<Worker> workers = new ArrayList<Worker>(MAX_WORKERS); private boolean roomLeft() { synchronized (workers) { return (workers.size() < MAX_WORKERS); } } private void addWorker() { synchronized (workers) { workers.add(new Worker(this)); } } public void removeWorker(Worker worker) { synchronized (workers) { workers.remove(worker); } } public Example() { while (true) { if (roomLeft()) { addWorker(); } } }

Donde el trabajador es su clase que extiende el hilo. Cada trabajador llamará al método removeWorker de esta clase, haciéndose pasar como un parámetro, cuando termine de hacer su trabajo.

Dicho esto, el marco Executor se ve mucho mejor.

Editar: ¿Alguien quiere explicar por qué esto es tan malo, en lugar de solo modificarlo?


Creo que Executors.newFixedThreadPool se ajusta a sus requisitos. Hay varias maneras diferentes de utilizar el ExecutorService resultante, dependiendo de si desea que se devuelva un resultado al hilo principal, o si la tarea es totalmente independiente, y si tiene una colección de tareas para realizar por adelantado, o si las tareas están en cola en respuesta a algún evento.

Collection<YourTask> tasks = new ArrayList<YourTask>(); YourTask yt1 = new YourTask(); ... tasks.add(yt1); ... ExecutorService exec = Executors.newFixedThreadPool(5); List<Future<YourResultType>> results = exec.invokeAll(tasks);

Alternativamente, si tiene una nueva tarea asíncrona para realizar en respuesta a algún evento, probablemente solo quiera utilizar el método de execute(Runnable) simple EjecutorService execute(Runnable) .



Executors.newFixedThreadPool (int)

Executor executor = Executors.newFixedThreadPool(n); Runnable runnable = new Runnable() { public void run() { // do your thing here } } executor.execute(runnable);


Como han mencionado otros aquí, la mejor opción es crear un grupo de subprocesos con la clase Ejecutores :

Sin embargo, si quiere hacer su propia versión, este código debería darle una idea de cómo proceder. Básicamente, simplemente agregue cada nuevo hilo a un grupo de hilos y asegúrese de que nunca tenga más de N hilos activos en el grupo:

Task[] tasks = getTasks(); // array of tasks to complete ThreadGroup group = new ThreadGroup(); int i=0; while( i<tasks.length || group.activeCount()>0 ) { if( group.activeCount()<N && i<tasks.length ) { new TaskThread(group, tasks[i]).start(); i++; } else { Thread.sleep(100); } }


  1. Si su cola de tareas no va a estar desbordada y las tareas pueden completarse en intervalos de tiempo más cortos, puede usar Executors.newFixedThreadPool(n) ; como lo sugieren los expertos.

    El único inconveniente en esta solución es el tamaño ilimitado de la cola de tareas. No tienes control sobre eso. El gran apilamiento en la cola de tareas degradará el rendimiento de la aplicación y puede causar falta de memoria en algunos escenarios.

  2. Si desea utilizar ExecutorService y habilitar el mecanismo de work stealing donde los subprocesos de trabajo inactivos comparten la carga de trabajo de los subprocesos de trabajo ocupados mediante el robo de tareas en la cola de tareas. Devolverá el tipo de servicio Ejecutor ForkJoinPool.

    public static ExecutorService newWorkStealingPool (int parallelism)

    Crea un grupo de subprocesos que mantiene suficientes subprocesos para admitir el nivel de paralelismo especificado y puede usar varias colas para reducir la contienda. El nivel de paralelismo corresponde a la cantidad máxima de subprocesos que participan activamente en, o disponibles para participar en, el procesamiento de tareas. La cantidad real de subprocesos puede crecer y reducirse de forma dinámica. Un grupo de robo de trabajo no garantiza el orden en que se ejecutan las tareas enviadas.

  3. Prefiero ThreadPoolExecutor debido a la flexibilidad en las API para controlar muchos parámetros, que controla la ejecución de la tarea de flujo.

    ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

en su caso, configure corePoolSize and maximumPoolSize as N Aquí puede controlar el tamaño de la cola de tareas, definir su propia fábrica de hilos personalizada y la política del controlador de rechazo.

Eche un vistazo a la pregunta SE relacionada para controlar dinámicamente el tamaño de la agrupación:

Grupo de hilos dinámico