2014-09-11 2 views
-1

Я пытаюсь понять потоки лучше, поэтому я выполняю простую задачу:Threads wating and waking up

У меня есть 2 класса, которые реализуют runnable. Каждый из них генерирует 2 случайных числа от 1 до 10. ClassA вычисляет сумму и ClassB умножение. Оба выполняют эту работу в цикле в течение 15 секунд.

У меня есть другой класс под названием General, который имеет 2 статических и синхронизированных метода: setVal и getVal. Каждый поток вызывает Gener.setVal (результат) после каждого вычисления/итерации. setVal устанавливает только значение, если оно ближе к числу, чем его предыдущее значение. getValue получает только значение.

У меня есть основной класс, который запускает каждую нить. Тогда есть цикл на 20 секунд, выводящий значение, заданное потоками. поэтому он просто вызывает getValue и печатает его.

Я хочу, чтобы каждый поток, после одной итерации, ожидал и уведомлял другого, чтобы сделать итерацию и т. Д. Как я могу это сделать?

Вот мой код:

public class Particle1 implements Runnable{ 

    //private int x; 
    private static final int max = 10; 
    private static final int min = 1; 

    public void run(){ 
     long t= System.currentTimeMillis(); 
     long end = t+15000; 
     while(System.currentTimeMillis() < end) { 
      Random rand = new Random(); 
      int a = rand.nextInt((max - min) + 1) + min; 
      int b = rand.nextInt((max - min) + 1) + min; 

      int x = a+b; 
      System.out.println("P1: "+a+"+"+b+"="+x); 
      Gather.setRes(x); 
      //i want it here to sleep until the other one wakes it up. 
     } 
    } 

} 


public class Particle2 implements Runnable{ 

    //private int x; 
    private static final int max = 10; 
    private static final int min = 1; 

    public void run(){ 
     long t= System.currentTimeMillis(); 
     long end = t+15000; 
     while(System.currentTimeMillis() < end) { 
      Random rand = new Random(); 
      int a = rand.nextInt((max - min) + 1) + min; 
      int b = rand.nextInt((max - min) + 1) + min; 

      int x = a+b;    
      System.out.println("P2: "+a+"+"+b+"="+x); 
      Gather.setRes(x); 
      //i want it here to sleep until the other one wakes it up. 
     } 
    } 

} 


public class Main { 

    public static void main(String[] args) throws InterruptedException { 

     Thread thread1 = new Thread(new Particle1()); 
     Thread thread2 = new Thread(new Particle2()); 
     thread1.start(); 
     thread2.start(); 


     long t= System.currentTimeMillis(); 
     long end = t+20000; 
     while(System.currentTimeMillis() < end) { 
      System.out.println("Minimum is: "+Gather.getRes()); 
      Thread.sleep(1000); 
     } 
     return; 
    } 

} 


public class Gather { 

    public Gather() { 
     // TODO Auto-generated constructor stub 
    } 

    private static int res=1000000; 

    public static int getRes() { 
     return res; 
    } 

    public synchronized static void setRes(int inres) { 
     if(Math.abs(inres-250)<res){ 
      res = inres; 
     } 
    } 



} 
+0

Вы имеете в виду две нити, чтобы работать антагонистически? (потому что это (вроде) побеждает цель многопоточности! – jbutler483

+1

Многие новички спрашивают, как сделать два или более потоков по очереди. Вы можете создать объект синхронизации, который сделает это, но вы не найдете такой объект в библиотеке, потому что _that это не те потоки for._ Всякий раз, когда у программы есть два или более потока, которые не могут работать в одно и то же время, вы можете сделать эту программу более простой (то есть лучше), имея только один поток, чтобы все работа. Все точки потоков - это то, что два или более потока могут одновременно делать разные вещи. –

ответ

1

Использование Нити обычно упражнение, когда вы хотите, чтобы все потоки, чтобы работать независимо друг от друга, а не в карцер шаге друг с другом.

Однако есть моменты, когда потоки должны связываться между собой - в этом случае для связи между ними обычно используется некоторая форма BlockingQueue. Вот пример:

public class TwoThreads { 
    public static void main(String args[]) throws InterruptedException { 
    System.out.println("TwoThreads:Test"); 
    new TwoThreads().test(); 
    } 

    // The end of the list. 
    private static final Integer End = -1; 

    static class Producer implements Runnable { 
    final Queue<Integer> queue; 

    public Producer(Queue<Integer> queue) { 
     this.queue = queue; 
    } 

    @Override 
    public void run() { 
     try { 
     for (int i = 0; i < 1000; i++) { 
      queue.add(i); 
      Thread.sleep(1); 
     } 
     // Finish the queue. 
     queue.add(End); 
     } catch (InterruptedException ex) { 
     // Just exit. 
     } 
    } 

    } 

    static class Consumer implements Runnable { 
    final Queue<Integer> queue; 

    public Consumer(Queue<Integer> queue) { 
     this.queue = queue; 
    } 

    @Override 
    public void run() { 
     boolean ended = false; 
     while (!ended) { 
     Integer i = queue.poll(); 
     if (i != null) { 
      ended = i == End; 
      System.out.println(i); 
     } 
     } 
    } 

    } 

    public void test() throws InterruptedException { 
    Queue<Integer> queue = new LinkedBlockingQueue<>(); 
    Thread pt = new Thread(new Producer(queue)); 
    Thread ct = new Thread(new Consumer(queue)); 
    // Start it all going. 
    pt.start(); 
    ct.start(); 
    // Wait for it to finish. 
    pt.join(); 
    ct.join(); 
    } 

} 

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