2016-12-06 14 views
0

イベントを待っているスレッドがあります。このスレッドに通知されると、私は目を覚ましたいと思いますし、REFRESH_TIMEよりも長い場合は、postInvalidateの呼び出しでビューを無効にします。それ以外の場合は、次のREFRESH_TIMEになるまでにスリープ状態になります。一方、他のイベントが描画するように通知しようとすると、次のREFRESH_TIMEが再びパスした直後に再度描画するようにフラグを設定する必要があります。さもなければ、それは次の通知まで無期限に待つでしょう(または、もちろん停止するように要求されますが、その部分は無視してください)。Androidビューアップデータスレッドは、Nミリ秒ごとに一度だけ更新され、オンデマンドでのみ表示されます。

私はこれをwaitとnotifyの同期ロック内で開発しようとしていましたが、私はそれを使うことはできません。タイムアウトのあるWaitForSingleObjectはC++のために気になりますが、Javaではまだ似たようなことをする機会はありませんでした。この問題に最も適したものは何ですか?

更新プログラムの実行中に100の通知が表示された場合は、それらを1つの通知として扱い、もう1つの無効化を追加して、次のREFRESH_TIMEミリ秒後に落としてください。言い換えると。アップデートは見逃せません。

ここにいくつかの不完全なコードがあります。どうすればそれを終えることができますか?

public class ViewInvalidator extends Thread { 

private View m_view; 

Object lock = new Object(); 
boolean ready = false; 
long m_refreshTimeMilliseconds; 
boolean m_threadRequestedToStop = false; 

public ViewInvalidator(View view, long refreshTimeMilliseconds) { 

    m_view = view; 
    m_refreshTimeMilliseconds = refreshTimeMilliseconds; 
} 

public void postInvalidate() { 

    synchronized(lock) { 

     ready = true; 
     lock.notifyAll(); 
    } 
} 

public void stopThread() { 

    synchronized (lock) { 

     while(!ready) 
      lock.notifyAll(); 
    } 
} 

@Override 
public void run() { 

    long lastPostInvalidate = System.currentTimeMillis(), timeSince; 

    while(true) { 

     if (this.m_threadRequestedToStop) 
      break; 

     try { 

      synchronized (lock) { 

       while (!ready) 
        lock.wait(); 

      } 
     } catch(InterruptedException e) { 

      System.out.println(e.getMessage()); 
      e.printStackTrace(); 
      break; 
     } 

     // someone just woke us up. Check if it was a request to stop. If it was, stop. 
     if (this.m_threadRequestedToStop) 
      break; 

     // if less time than our refresh time, sleep for the difference, then invalidate. Otherwise just invalidate. 
     timeSince = System.currentTimeMillis() - lastPostInvalidate; 
     if(timeSince < m_refreshTimeMilliseconds) 
      try { 
       Thread.sleep(m_refreshTimeMilliseconds - timeSince); 
      } catch(InterruptedException e) {} 

     m_view.postInvalidate(); 
    } 
} 

おかげでたくさん、 マイク

+0

このスレッドの目的をさらに詳しく説明できますか?現在のところ、ブロッキングやタイマーを使用するのではなく、このスレッドが必要な理由は不明です – Tosh

+0

私は、UIを別々に更新する責任があるスレッドがたくさんあります。 REFRESH_TIMEで区切られていないときに、不必要にコールを無効にしないようにコールを集約したいアップデータスレッドはそれを行い、その間に余分なものを取り消し、1として扱います。これにより、個々のスレッドは再描画が必要だと言うことができます。 – Mike

+0

私はその部分を理解していますが、あなたのプログラムが正常に再描画するたびにブール値を使用してチェックすることができない理由がないようです。 – Tosh

答えて

0
long lastPostInvalidate; 
bool running; 
bool valid; 

public void f(){ 
if(running)if(!valid)synchronized(valid){valid=true;} 
else { 
running = true; 
while(func()){}; 
running = false; 
} 

private bool func() { 
synchronized (valid){valid = false;} 
synchronized (lastPostInvalidate) { 
long next = System.currentTimeMillis(); 
long x = next - timeSincelastPostInvalidate; 
x = m_refreshTimeMilliseconds-x; 
if(x>0)sleep(x); 
m_view.postInvalidate(); 
timeSincelastPostInvalidate = next; 
}return valid; 
} 

は、その使用条件を忘れました。実際にはこのように見えるはずです。つまり、このようにすると、アップデートの途中で頻繁にアップデートすることが予想される場合は、更新スレッドをロックする可能性があります。ただし、頻繁に更新が必要な場合は、最初に計画したとおりにスレッドを使用することもできますが、非アクティブにする必要はありません。

関連する問題