2014-04-17 3 views
2

В настоящее время я работаю над проектом, в котором у меня есть по существу 10 нитей, которые «спят». Случайно один из этих 10 потоков должен «проснуться» и начать делать некоторые работы. Я просто хочу посмотреть, пойду ли я в правильном направлении. Поэтому я должен просто создать каждый экземпляр потока, например.Спящие темы в JAVA

Thread thread0 = new Thread(new doWork()); 
... 
Thread thread9 = new Thread(new doWork()); 

и просто не запускать их, а затем, когда они должны «разбудить» просто вызовите start() метод на конкретной теме ..

или я должен начать каждый поток, но у них wait(), пока я не называю notify() способ?

или я должен начать тему и использовать sleep(), а затем позвонить по методу interrupt()?

Какой подход кажется лучше и почему?

Любое понимание очень ценится.

Редактировать Будет ли это приемлемо ??

import java.util.Random; 

public class Client { 

private static Thread [] clients = new Thread[10]; 

public static void main(String[] args){ 

    createClients(); 
    randomWake(); 

}// end main() 

static void createClients(){ 

    Thread client0 = new Thread(new ClientThread(0)); 
    clients[0] = client0; 
    Thread client1 = new Thread(new ClientThread(1)); 
    clients[1] = client1; 
    Thread client2 = new Thread(new ClientThread(2)); 
    clients[2] = client2; 
    Thread client3 = new Thread(new ClientThread(3)); 
    clients[3] = client3; 
    Thread client4 = new Thread(new ClientThread(4)); 
    clients[4] = client4; 
    Thread client5 = new Thread(new ClientThread(5)); 
    clients[5] = client5; 
    Thread client6 = new Thread(new ClientThread(6)); 
    clients[6] = client6; 
    Thread client7 = new Thread(new ClientThread(7)); 
    clients[7] = client7; 
    Thread client8 = new Thread(new ClientThread(8)); 
    clients[8] = client8; 
    Thread client9 = new Thread(new ClientThread(9)); 
    clients[9] = client9; 

    for(int i = 0; i < clients.length; i++) 
     clients[i].start(); 

}// end createClients() 

static void randomWake(){ 

    Random rand = new Random(); 
    int randomNumber = rand.nextInt(10); 

    clients[randomNumber].interrupt(); 

}// end randomWake() 

static class ClientThread implements Runnable{ 

    private int clientNumber; 

    public ClientThread(int clientNumber){ 
     this.clientNumber = clientNumber; 
    }// end ClientThread(int clientNumber) 

    public void run(){ 
     while(!Thread.interrupted()){} 
     System.out.println("Client " + clientNumber + " is awake!"); 
    }// end run() 

}// end class ClientThread 

} // конец класса Client

+2

Как насчет ExecutorService исполнитель = Executors.newFixedThreadPool (10); ? – chro

+0

@cho: Это может произойти событие. Hower вопрос утверждает, что потоки активируются «случайно» ... –

ответ

0

В случае, если максимальное количество времени сна

Вы, вероятно, нужно будет реализовать следующий Thread класс:

public class DoWork extends Thread { 

    public void run() { 
     while(true) { 
      Thread.Sleep((int) Math.floor(Math.random()*10000)); 
      //do some work 
     } 
    } 

} 

Где 10000 - это максимальное время в миллисекундах, когда нить должна спать.

В случае нет максимального количества времени сна

Вы, вероятно, нужны будете реализовать следующий Thread класс:

public class DoWork extends Thread { 

    public void run() { 
     while(true) { 
      Thread.Sleep(1); 
      if(Math.random() < 0.005d) { 
      //do some work 
      } 
     } 
    } 

} 

где 0.005 вероятность запуска метода определенной миллисекунды ,


notify и wait используются для реализации семафоров: это объекты, которые мешают два потока, чтобы манипулировать и тот же объект одновременно (поскольку некоторые объекты могут в конечном итоге в незаконном состоянии).

+2

реализует Runnable? –

+1

или 'extends Thread'? –

+0

:-) теперь завершено –

0

Как насчет семафоров?

class DoWork extends Runnable { 
    private final Semaphore semaphore; 

    DoWork(Semaphore semaphore) { 
     this.semaphore = semaphore; 
    } 

    @Override 
    public void run() { 
     while (true) { 
      semaphore.acquire(); 
      //do some work 
     } 
    } 
} 

Основная программа может создать массив семафоров, и равное количество потоков, запущенных экземпляры DoWork, так что каждый экземпляр DoWork имеет свой собственный семафор. Каждый раз, когда основная программа вызывает sema [i] .release(), метод run() соответствующего экземпляра DoWork «выполняет некоторую работу», а затем возвращается к ожиданию.

0

Это не имеет большого смысла в вашем ответе, поэтому не уверен, чего вы действительно хотите достичь.Но за то, что вы описали, вы должны поставить все потоки, ожидающие на одной и той же блокировке, и просто уведомить блокировку (она пробудится только один случайным образом)

Но, поскольку это не имеет большого смысла, я думаю, вы хотите достичь чего-то другого ,

Проверить этот вопрос относительно сна против ожидания: Difference between wait() and sleep()

0

Проверить этот один. Вот как бы я решил это, если бы не использовать ThreadPooling (что очень правильно, как говорили другие), и поэтому я вижу, как работают wait(), notify() и Thread.sleep(). При проверке google вы увидите (например, Thread.sleep and object.wait), что главным образом wait() и notify() используются для связи между потоками и Thread.sleep, поэтому вы можете приостановить свою программу.

-Часть этого ответа основывается на этом: http://tutorials.jenkov.com/java-concurrency/thread-signaling.html#missedsignals. Вы можете проверить код, чтобы увидеть шаги, которые вам нужно предпринять (закомментировать некоторые части кода), чтобы ваша программа зависла, чтобы вы поняли, как работать с пропущенными сигналами. Итерации, необходимые для зависания вашей программы, не исправлены.

-Программа будет работать вечно. Вам нужно будет немного поработать над этим, чтобы исправить это.

Главная

public class Main 
{ 
    public static void main(String[] args) 
    { 
     Manager mgr = new Manager("manager"); 
     mgr.start(); 
    } 
} 

менеджер

public class Manager extends Thread 
{ 
    private final Object lock = new Object(); 
    private boolean wasSignalled = false; 

    private DoWork[] workThreads = new DoWork[5]; 

    public Manager(String name){ 
     super(name); 

     workThreads[0] = new DoWork(this,"work 0"); 
     workThreads[1] = new DoWork(this,"work 1"); 
     workThreads[2] = new DoWork(this,"work 2"); 
     workThreads[3] = new DoWork(this,"work 3"); 
     workThreads[4] = new DoWork(this,"work 4"); 
    } 


    public void wakeUP() 
    { 
     synchronized (this.lock) { 
      wasSignalled = true; 
      this.lock.notify(); 
     } 
    } 
    public void pauseAndWait() 
    { 
     synchronized (this.lock) { 
      if(!wasSignalled) 
      { 
       try { 
        this.lock.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      //clear signal and continue running. 
      wasSignalled = false; 
     } 
    } 

    public void run() 
    { 
     int i=0; 
     while(true) 
     { 
      i++; 
      System.out.println(" manager ...: "+i+" "); 

      int choose = 0 + (int)(Math.random() * ((4 - 0) + 1)); 
      //choose=0; for debugginng 

      if(!workThreads[choose].isAlive()){ 
       workThreads[choose].start(); 
      } 
      else{ 
       workThreads[choose].wakeUP(); 
      } 

      //wait to be notified by DoWork thread when its job 
      //is done 
      pauseAndWait(); 
     } 
    } 
} 

DoWork

public class DoWork extends Thread 
{ 
    private final Object lock = new Object(); 
    private boolean wasSignalled = false; 

    private Manager managerThread; 

    public DoWork(Manager managerThread,String name){ 
     super(name); 

     this.managerThread=managerThread; 
    } 


    public void wakeUP() 
    { 
     synchronized (this.lock) { 

      //check what happens without wasSignalled flag 
      //step #1: comment out wasSignalled = true; 
      wasSignalled = true;  
      this.lock.notify(); 
     } 
    } 
    public void pauseAndWait() 
    { 
     synchronized (this.lock) { 
      //check what happens without wasSignalled flag 
      //step #2: comment out the if block 
      if(!wasSignalled) 
      { 
       try { 
        this.lock.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 

      //check what happens without wasSignalled flag 
      //step #3: comment out wasSignalled = false; 

      //clear signal and continue running. 
      wasSignalled = false; 
     } 
    } 

    public void run() 
    { 
     int i=0; 
     while(true) 
     {   
      i++; 

      try { 
       System.out.print(this.getName()+" going to sleep ...: "+i+" "); 

       //check what happens without wasSignalled flag 
       //step #4: put sleep time to Thread.sleep(0); 

       //simulate worker thread job 
       Thread.sleep(1000); 
       System.out.println(" woke up ... "); 
      } catch (InterruptedException e) { 
       System.out.println(" worker thread: job simulation error:"+e); 
      } 

      //if worker thread job simulation is done (sleep for 4 times) 
      //then suspend thread and wait to be awaken again 
      if(i>4) 
      { 
       System.out.println(this.getName()+" notifying main ...: "+i+" \n"); 
       i=0; 
       managerThread.wakeUP(); 

       // thread does not get destroyed, it stays in memory and when the manager 
       // thread calls it again it will wake up do its job again 
       pauseAndWait(); 
      } 
     } 
    } 
}