2013-04-12 2 views
7

Как проверить, работает ли поток в пуле потока ExecutorService?Как проверить, работает ли поток в пуле приложений ExecutorService

Фон:
Я хочу синхронизировать между потоками в пуле потоков, если установлен флаг. Итак, если для синхронизации установлено значение true, то мне нужно проверить, работают ли другие потоки или дождаться его завершения, а затем вызвать блокирующий поток с синхронизацией, чтобы другие потоки дождались завершения этой блокирующей нити.

Если флаг не установлен, нет необходимости синхронизировать и может выполнять потоки параллельно.

Спасибо!

+1

Можете ли вы дать нам некоторый контекст относительно того, что/почему вы делаете? –

+0

попробовал thread.isAlive()? – Ankit

+0

Что значит? Вы имеете в виду, работает ли _task_? В «ExecutorService» всегда будет «Threads». Пожалуйста, разместите свой код, чтобы мы могли помочь вам, а не догадываться о том, что вам может понадобиться. –

ответ

5

Вам необходимо использовать Semaphore.

Это позволяет вам иметь ряд «разрешений» для выполнения работы. Если вы хотите, чтобы одна задача выполнялась одновременно, то есть Semaphore с одним разрешением, в противном случае есть Semaphore с числом разрешений, превышающим число Thread s в пуле.

static class Worker implements Runnable { 

    final Semaphore semaphore; 

    public Worker(Semaphore semaphore) { 
     this.semaphore = semaphore; 
    } 

    @Override 
    public void run() { 
     try { 
      semaphore.acquire(); 
      try { 
       //do stuff 
      } finally { 
       semaphore.release(); 
      } 
     } catch (InterruptedException ex) { 
      Thread.currentThread().interrupt(); 
     } 
    } 
} 

public static void main(String[] args) { 

    final int numThreads = 10; 
    final ExecutorService executorService = Executors.newFixedThreadPool(10); 
    final Semaphore semaphore; 
    boolean myflag = true; 
    if (myflag) { 
     semaphore = new Semaphore(1); 
    } else { 
     semaphore = new Semaphore(numThreads); 
    } 
    final Worker worker = new Worker(semaphore); 
    executorService.submit(worker); 
} 

Этот пример немного надуманный, как вы можете просто использовать newSingleThreadExecutor(), когда вам нужно только одно задание для запуска в то время, - но я полагаю, вы знаете, что и по какой-то причине не может.

EDIT

После пошарил немного, чтобы увидеть, если это может быть прибрано я наткнулся на this. Это намекает на аккуратным решение:

static interface TaskBlocker { 

    void acquire(); 

    void release(); 
} 

static class Worker implements Runnable { 

    final TaskBlocker taskBlocker; 

    public Worker(TaskBlocker taskBlocker) { 
     this.taskBlocker = taskBlocker; 
    } 

    @Override 
    public void run() { 
     taskBlocker.acquire(); 
     try { 
      //do stuff 
     } finally { 
      taskBlocker.release(); 
     } 
    } 
} 

public static void main(String[] args) { 

    final int numThreads = 10; 
    final ExecutorService executorService = Executors.newFixedThreadPool(numThreads); 
    final TaskBlocker taskBlocker; 
    boolean myflag = true; 
    if (myflag) { 
     taskBlocker = new TaskBlocker() { 
      final Lock lock = new ReentrantLock(); 

      @Override 
      public void acquire() { 
       lock.lock(); 
      } 

      @Override 
      public void release() { 
       lock.unlock(); 
      } 
     }; 
    } else { 
     taskBlocker = new TaskBlocker() { 
      @Override 
      public void acquire() { 
      } 

      @Override 
      public void release() { 
      } 
     }; 
    } 
    final Worker worker = new Worker(taskBlocker); 
    executorService.submit(worker); 
} 
+0

Вы получаете тот же эффект с SingleThreadExecutor? – Bhargav

+0

@Bhargav какой эффект? –

+0

Знаешь. что только 1 задача выполняется в заданное время – Bhargav

3

Короче говоря, вы этого не сделаете. Исполнители не должны использоваться таким образом. Если вы хотите управлять своими потоками вручную, сделайте это без Executors. Если вы используете Исполнителей, переместите свое мышление с Thread s до Runnable s. Сделайте свои Runnables или классы и методы потокобезопасными, используя синхронизацию или любые абстракции высокого уровня в java.util.concurrent.

3

Как я могу проверить, если поток выполняется в пуле потоков ExecutorService?

Это действительно не имеет смысла в контексте пула потоков ExecutorService. Пул выполняет ваши классы Runnable (или Callable). Возможно, вы должны спросить, может ли вы увидеть, работает ли конкретная работа в пуле или нет.

Если вы хотите сделать это, то каждый из рабочих мест, в передней части методы run() (или call()) можно проверить, какое-то synchronized объекта и ждать или продолжать по мере необходимости. Возможно также, что у вас может быть несколько пулов потоков и разделить ваши задания на более мелкие части, чтобы вы могли контролировать, какие части ваших заданий выполняются одновременно.

Однако, как правило, @Ralf указывает, что вы делаете это против всей точки потока-пула. Весь смысл потоков-пулов в том, что задания выполняются асинхронно. Если вам требуется много точек синхронизации, возможно, вам придется перепроектировать.

Если вы дадите более подробную информацию о своей среде, мы сможем более конкретно рассмотреть ваш основной вопрос.

+0

Кто-нибудь хочет добавить обратную связь в нижний угол? – Gray

3

Как проверить, работает ли поток в пуле потока ExecutorService?

Если вы просто хотите знать, если поток выполняется в определенном ExecutorService, вы можете создать ExecutorService с конкретным ThreadFactory и он приложить некоторые специальные свойства для резьбы, такие как специальное название.

private static final String EXECUTOR_THREADNAME_PREFIX = "ExecutorThread"; 

ThreadFactory threadFactory = new ThreadFactory() { 

    private final AtomicInteger id = new AtomicInteger(0); 

    @Override 
    public Thread newThread(Runnable r) { 
     Thread thread = new Thread(r); 
     thread.setName(EXECUTOR_THREADNAME_PREFIX + "_" + id.incrementAndGet()); 
     return thread; 
    } 
}; 

myExecutor = Executors.newCachedThreadPool(threadFactory); 

Затем в потоке, вы просто проверить, если имя начинается с префикса:

if (Thread.currentThread().getName().startsWith(EXECUTOR_THREADNAME_PREFIX)) { 
    // In executor. 
} else { 
    // Not in executor. 
} 
Смежные вопросы