2016-05-03 3 views
1

Я пытаюсь настроить поток таймера, который через секунду увеличивает счетчик и выводит результат на терминал.Timer Deadlock Issue

public class SecondCounter implements Runnable 
{ 
private volatile int counter; 
private boolean active; 
private Thread thread; 

public SecondCounter() 
{ 
    counter = 0; 
    active = true; 
    thread = new Thread(this); 
    thread.start(); 
} 

public int getCount() 
{ 
    return counter; 
} 

public void run() 
{ 
    while(active) 
    { 
     try { 
      Thread.sleep(1000); 
     } catch(InterruptedException ex) {ex.printStackTrace();} 

     synchronized(this) 
     { 
      System.out.print(++counter+" "); 
      try{ 
       notifyAll(); 
       wait(); 
      } catch(InterruptedException ex) {ex.printStackTrace();} 
     } 
    } 
} 

Тогда, у меня есть еще один метод в классе под названием messagePrinter(), который принимает в целом, создает новый поток, и контролирует основной поток таймера, чтобы увидеть, когда кратна этой ИНТ на счете:

public synchronized void messagePrinter(final int x) 
{ 
    Runnable mp = new Runnable() 
    { 
     public void run() 
     { 
      while(active) 
      { 
       synchronized(this) 
       { 
        try { 
         while(counter%x != 0 || counter == 0) 
         { 
          notifyAll(); 
          wait(); 
         } 
         System.out.println("\n"+x+" second message"); 
         notifyAll(); 
        } catch(InterruptedException ex) {ex.printStackTrace();} 
       } 
      } 
     } 
    }; 
    new Thread(mp).start(); 
} 

Я пытался возиться с ожиданием() и notifyAll() совсем немного, но каждый комбинации я попытался результаты в обоих потоков, входящих в состояние ожидания и вызывая затор. Или, поток таймера запустит все время потока и никогда не даст сообщениюPrinter возможность проверить, что подсчитывает в настоящее время.

Вот что результат должен выглядеть следующим образом:

1 2 3 
3 second message 
4 5 6 
3 second message 

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

Вот мой главный файл:

public class Main2 
{ 
    public static void main(String[] args) 
    { 
     SecondCounter c = new SecondCounter(); 
     c.messagePrinter(3); 
    } 
} 

Любой с некоторым заправочным уходом опыта, чтобы дать мне некоторое представление о том, где я неправильно?

EDIT: Я преобразовал свой целочисленный счетчик в атомное целое число, и я изменил сообщениеPrinter для синхронизации на «SecondCounter.this» вместо «this». Теперь работает! В основном, в любом случае, он печатает «x second message» примерно тридцать раз, когда существует несколько MessagePrinters. Я думаю, что могу это исправить.

+0

Преобразовать «считать» объект быть атомным числом –

+1

Ваш 'раздел synchronized' синхронизируются различными' это 'объектов. Первый использует экземпляр «SecondCounter», второй использует экземпляр вашего созданного «Runnable». Я довольно новичок в java, но я думаю, что вы должны использовать 'synchronized (SecondCounter.this)' во втором случае (и 'SecondCounter.wait' /' SecondCounter.notifyAll'). –

+0

Я дам вам попробовать, спасибо! – Araganor

ответ

0

У меня он работает сейчас, вот мой рабочий код:

import java.util.concurrent.atomic.AtomicInteger; 

public class SecondCounter implements Runnable 
{ 
private volatile AtomicInteger counter; 
private boolean active; 
private boolean printed; 
private Thread thread; 

public SecondCounter() 
{ 
    counter = new AtomicInteger(0); 
    active = true; 
    thread = new Thread(this); 
    thread.start(); 
} 



public void run() 
{ 

    while(active) 
    { 
     try { 
      Thread.sleep(1000); 
     } catch(InterruptedException ex) {ex.printStackTrace();} 

     synchronized(this) 
     { 
      System.out.print(counter.incrementAndGet()+" ");  
      printed = false; 
      try{ 
       this.notify(); 
       this.wait(); 
      } catch(InterruptedException ex) {ex.printStackTrace();} 
     } 
    } 
} 

public synchronized void messagePrinter(final int x) 
{ 
    Runnable mp = new Runnable() 
    { 
     public void run() 
     { 
      while(active) 
      { 
       synchronized(SecondCounter.this) 
       { 
        try { 
         while(counter.get()%x != 0 || counter.get() == 0) 
         { 
          SecondCounter.this.notify(); 
          SecondCounter.this.wait(); 
         } 
         if(!printed) 
         { 
          System.out.println("\n"+x+" second message"); 
          printed = true; 
         } 
         SecondCounter.this.notify(); 
         SecondCounter.this.wait(); 
        } catch(InterruptedException ex) {ex.printStackTrace();} 
       } 
      } 
     } 
    }; 
    new Thread(mp).start(); 
} 

}