2013-08-08 27 views
6

Farklı iş parçacıklarında birçok görevi çalıştırmak için ExecutorService kullanıyorum. Bazen, iş parçacığı havuzunda bekleyen çok fazla Runnable örneği Bellek Dolu sorununa neden olabilir.ExecutorService'deki konuları nasıl sınırlarsınız?

Çözmek için engelleme görev yürütücüsü yazmayı denerim. Bunu yapmak için herhangi bir resmi çözüm var mı? Örneğin

:

burada
BlockingJobExecutor executor = new BlockingJobExecutor(3); 
    for (int i = 0; i < 1000; i++) { 
     executor.addJob(new Runnable() { 

      @Override 
      public void run() { 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       LogFactory.getLog(BTest.class).info("test " + System.currentTimeMillis()); 
      } 
     }); 
    } 
    executor.shutdown(); 

BlockingJobExecutor sınıftır:

bunun iki yolu vardır
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.TimeUnit; 
import java.util.concurrent.atomic.AtomicInteger; 

public class BlockingJobExecutor { 

    AtomicInteger counter = new AtomicInteger(); 
    ExecutorService service; 
    int threads; 

    public BlockingJobExecutor(int threads) { 
     if (threads < 1) { 
      throw new IllegalArgumentException("threads must be greater than 1."); 
     } 
     service = Executors.newFixedThreadPool(threads); 
     this.threads = threads; 
    } 

    static class JobWrapper implements Runnable { 
     BlockingJobExecutor executor; 
     Runnable job; 

     public JobWrapper(BlockingJobExecutor executor, Runnable job) throws InterruptedException { 
      synchronized (executor.counter) { 
       while (executor.counter.get() >= executor.limit()) { 
        executor.counter.wait(); 
       } 
      } 
      this.executor = executor; 
      this.job = job; 
     } 

     @Override 
     public void run() { 
      try { 
       job.run(); 
      } finally { 
       synchronized (executor.counter) { 
        executor.counter.decrementAndGet(); 
        executor.counter.notifyAll(); 
       } 
      } 
     } 
    } 

    public int limit() { 
     return threads; 
    } 

    public void shutdown() { 
     service.shutdown(); 
     try { 
      service.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); 
     } catch (InterruptedException e) { 
      throw new RuntimeException(e); 
     } 
    } 

    public void addJob(Runnable job) { 
     try { 
      service.execute(new JobWrapper(this, job)); 
     } catch (InterruptedException e) { 
      throw new RuntimeException(e); 
     } 
    } 

} 
+0

Çalıştırmayı bekleyen çok fazla işiniz olduğunu veya aynı anda çok fazla iş parçacığınızın olduğunu mu düşünüyorsunuz? – chrylis

+0

Çalıştırmak için bekleyen çok fazla iş var. – qrtt1

cevap

12

. Çalıştırmayı bekleyen sıraya alınmış çok sayıda runnable veya aynı anda çok fazla iş parçacığı çalıştırabilirsiniz. Sıraya alınmış çok fazla iş varsa, sıraya alınabilecek öğelerin sayısını sınırlamak için ExecutorService numaralı BlockingQueue sabit boyutunu kullanabilirsiniz. Daha sonra yeni bir görevi kuyruğa almaya çalıştığınızda, işlem sıraya girene kadar engellenir.

Aynı anda çok fazla iş parçacığı varsa, istediğiniz iş parçacığı sayısıyla Executors.newFixedThreadPool numaralı telefonu arayarak ExecutorService'de görevleri çalıştırmak için kaç iş parçacığının kullanılabileceğini sınırlandırabilirsiniz.

İlgili konular