2015-09-24 3 views
2

Я пытаюсь напечатать синхронизированный объект Integer (mInt) с использованием двух потоков до 10. Однако ни один из потоков не блокирует другой поток, генерирует исключение, вставленное ниже. Может кто-то указать мою ошибку здесь. Это скорее вопрос, связанный с Java, но включающий тег «android», потому что я закодировал его для Android, и мне нужно попробовать где-то в нем.Пытается печатать четные и нечетные числа из общего ресурса

09-24 15: 24: 17,198 10621-11400/com.sameer.android.samplecode Е/AndroidRuntime: неустранимый: резьба-364 процесс: com.sameer.android.samplecode, ПИД: 10621 java.lang.IllegalMonitorStateException: объект не заблокирован нитью перед уведомлением() на java.lang.Object.notify (собственный метод) на com.sameer.android.samplecode.MainActivity $ Even.run (MainActivity.java:55)

public class MainActivity extends AppCompatActivity { 
    private Integer mInt; 

    class Odd extends Thread { 
     private final String TAG = Odd.class.getSimpleName(); 

     @Override 
     public void run() { 
      Log.i(TAG, "Odd() Started...."); 
      synchronized (mInt) { 
       try { 
        while (mInt <= 10) 
        { 
         while (mInt % 2 != 1) { 
          Log.i(TAG, "Odd... Looping " + mInt); 
          mInt.wait(); 
         } 
         mInt++; 
         Log.i(TAG, "Odd " + mInt); 
         mInt.notify(); 
        } 
       } 
       catch (InterruptedException e) { 
        Log.e(TAG, "Odd() " + e.getMessage()); 
       } 
      } 
      Log.i(TAG, "Odd() Ended...."); 
     } 
    } 

    class Even extends Thread { 
     private final String TAG = Even.class.getSimpleName(); 

     @Override 
     public void run() { 
      Log.i(TAG, "Even() Started...."); 
      synchronized (mInt) { 
       try { 
        while (mInt <= 10) 
        { 
         while (mInt % 2 != 0) { 
          Log.i(TAG, "Even... Looping " + mInt); 
          mInt.wait(); 
         } 
         mInt++; 
         Log.i(TAG, "Even " + mInt); 
         mInt.notify(); 
        } 
       } 
       catch (InterruptedException e) { 
        Log.e(TAG, "Even() " + e.getMessage()); 
       } 
      } 
      Log.i(TAG, "Even() Ended...."); 
     } 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mInt = new Integer(0); 
     Button button = (Button) findViewById(R.id.button); 
     button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Even even = new Even(); 
       even.start(); 

       Odd odd = new Odd(); 
       odd.start(); 
      } 
     }); 
    } 
} 

ответ

1

При увеличиваем mInt, вы делаете не изменяете текущий объект Integer, но создать новый объект Integer. Таким образом, вызов notify выполняется на новом (разблокированном) объекте. Поскольку notify должен быть вызван на объект, который заблокирован, происходит IllegalMonitorStateException.

Дополнительная Сторона Примечание (не часть ответа):

Ваш код имеет фундаментальную проблему. Вы блокируете mInt в начале обоих методов run. Таким образом, только один из ваших потоков может ввести свой блок synchronized. Второй поток будет ждать блокировки на mInt до тех пор, пока первая нить не покинет его. synchronized блок, т. Е. Завершается. Таким образом, вы попадаете в тупик , потому что первый поток увеличивается только один раз и ждет внутри своего блока synchronized для другого потока, чтобы сделать следующий шаг. Однако второй поток не может выполнить эту операцию, так как он не может ввести свой собственный блок synchronized (пока первый поток не освободит блокировку на mInt).

+0

Эй, Матиас, вы первый пара имели отношение ко мне. Цените свой комментарий. – Sameer

+1

Я чувствую, что вы также должны отредактировать второй параграф. Возможно, я обманываю других. – Sameer

0

Thanks Matthias! Ваш ответ (частично) помог мне решить вопрос, который я подозревал, и вы его пригвоздили. Проблема заключалась в том, что mInt получил новое создание и, следовательно, потерял ссылку. Я исправил проблему, создав класс, подобный Integer. Я вставил код ниже.

import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 

public class MainActivity extends AppCompatActivity { 
    private Value mInt; 

    class Odd extends Thread { 
     private final String TAG = Odd.class.getSimpleName(); 

     @Override 
     public void run() { 
      Log.i(TAG, "Odd() Started...."); 
      synchronized (mInt) { 
       try { 
        while (mInt.get() < 10) 
        { 
         while (mInt.get() % 2 != 1) { 
          mInt.wait(); 
         } 
         Log.i(TAG, "Odd " + mInt.get()); 
         mInt.inc(); 
         mInt.notify(); 
        } 
       } 
       catch (InterruptedException e) { 
        Log.e(TAG, "Odd() " + e.getMessage()); 
       } 
      } 
      Log.i(TAG, "Odd() Ended...."); 
     } 
    } 

    class Even extends Thread { 
     private final String TAG = Even.class.getSimpleName(); 

     @Override 
     public void run() { 
      Log.i(TAG, "Even() Started...."); 
      synchronized (mInt) { 
       try { 
        while (mInt.get() < 10) 
        { 
         while (mInt.get() % 2 != 0) { 
          mInt.wait(); 
         } 
         Log.i(TAG, "Even " + mInt.get()); 
         mInt.inc(); 
         mInt.notify(); 
        } 
       } 
       catch (InterruptedException e) { 
        Log.e(TAG, "Even() " + e.getMessage()); 
       } 
      } 
      Log.i(TAG, "Even() Ended...."); 
     } 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mInt = new Value(); 
     Button button = (Button) findViewById(R.id.button); 
     button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       mInt.set(); 
       Even even = new Even(); 
       even.start(); 

       Odd odd = new Odd(); 
       odd.start(); 
      } 
     }); 
    } 
} 

class Value { 
    private int member; 

    public Value() { 
     member = 0; 
    } 

    public int get() { 
     return member; 
    } 

    public void inc() { 
     this.member++; 
    } 

    public void set() { 
     this.member = 0; 
    } 

    public void dec() { 
     this.member--; 
    } 
} 
Смежные вопросы