I know timers work by making the thread sleep for x amount of time but I was wondering if there is some sort of timer out there that doesn't run on a thread that's not the UI thread. I thought about using a loop that constantly compares the system time in milliseconds, but I want to use that as a last resort as it does not seem very efficient.
EDIT:
Stacktrace:
07-25 14:38:38.037 22108-22124/com.example.myapp E/ViewRootImpl﹕ com.example.myapp.Main : Only the original thread that created a view hierarchy can touch its views.
java.lang.RuntimeException
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6355)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:929)
at android.view.ViewGroup.invalidateChildFast(ViewGroup.java:4466)
at android.view.View.invalidateViewProperty(View.java:11112)
at android.view.View.setTranslationY(View.java:10472)
at android.view.View.setY(View.java:10400)
at com.example.myapp.Player.update(Player.java:29)
at com.example.myapp.Main.update(Main.java:70)
at com.example.myapp.Main.access$000(Main.java:15)
at com.example.myapp.Main$1.run(Main.java:33)
at java.util.Timer$TimerImpl.run(Timer.java:284)
Relative Code:
if (!onGround){
playerVisual.setY(playerVisual.getY() + this.gravity);
}
if (playerVisual.getY() >= this.main.getDevice().getHeight() - 10){
this.onGround = true;
}
else {
this.onGround = false;
}
playerVisual is an ImageView if you were wondering.
This is a solution based on AsyncTask:
class AsyncTimer extends AsyncTask<Void, Void, Void>
{
boolean alive = true;
long startMS;
long intervalMS;
MainActivity activity;
public AsyncTimer(long startMS, long intervalMS, MainActivity activity)
{
this.startMS = startMS;
this.intervalMS = intervalMS;
this.activity = activity;
}
protected Void doInBackground(Void... params)
{
try
{
Thread.sleep(startMS);
}
catch (Exception e)
{
Log.e("Error", e.getMessage());
e.printStackTrace();
}
while (alive)
{
try
{
alive = activity.updateUI();
Thread.sleep(intervalMS);
}
catch (Exception e)
{
Log.e("Error", e.getMessage());
e.printStackTrace();
}
}
return null;
}
}
Using it in MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
...
new AsyncTimer(0, 1000, this).execute();
}
public boolean updateUI()
{
Log.d("Timer", "tick");
...
return true;
}
This is a solution for updating the GUI from a scheduled task. Use Handler instead of Timer
final Handler handler = new Handler();
final Runnable myRunnable = new Runnable()
{
public void run()
{
handler.postDelayed(myRunnable, 1000); //1 second
/*UPDATE GUI*/
update();
}
};
myRunnable.run();
You bascially want to block the current thread / wait on a condition - well
there are several options - the easiest one is to use Semaphore :
final Semaphore semaphore = new Semaphore(0); //not available at first
try
{
semaphore.tryAcquire(1, TimeUnit.SECONDS); //block for 1 second since it isnt available
}
catch(InterruptedException ex)
{
//do something sensible here
}
Another option is CountDownLatch :
final CountDownLatch latch = new CountDownLatch(1); //1 latch available
try
{
latch.await(1, TimeUnit.SECONDS) //since currently one latch is available this will timeout
}
catch(InterruptedException ex)
{
//do something sensible here
}
Granted : thats somewhat of an abuse of these classes, but it works flawlessy.
You could even use Object.wait but since an object can receive "spurious wakeups" you would have to deal with those - which isnt always as easy as it may appear to be at first.
Basically, you can use pretty much any mechanism which allows you to reliably "wait" on something - until your next time-slice is ready to be taken (hence : timeout on something) and continue in your loop.
In languages other than Java its possible to (reliably) suspend / pause the current thread for a fixed amount of time - thats even better but it breaks quite a few programming paradigms and it can be hard to understand; its best to not touch the thread itself unless you're really experienced and have a lot of knowledge about these things, blocking method invocations are almost always the best choice, even if that means writing a few extra lines of code.
Related
I have a CustomAsyncTask class that enables infinite barcode scanner and I execute it in CustomApplication.
Unfortunately CustomAsyncTask::doInBackground stops after some time (minute or two).
private class ScanAsync extends AsyncTask<Void, String, Void>
{
boolean blocked = false;
#Override
protected Void doInBackground(Void... params)
{
while(true)
{
if (!blocked)
{
String received = GlobalAccess.scan.scan(500);
if (received != null && !received.isEmpty())
{
blocked = true;
publishProgress(received);
}
}
else
{
try
{
Thread.sleep(500);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
#Override
protected void onProgressUpdate(String... values)
{
super.onProgressUpdate(values);
//TODO: something with received value
blocked = false;
}
}
I need this background task to be always on. Is there any good solution for this? I have tried IntentService, but the result was the same - after some time it stopped working.
EDIT
I have created this Service, although it block my main thread, but it should work in background right? Also If I put a breakpoint on if(!blocked) and press F9 it works fine (scanning part), but if I remove breakpoint and let it run - after few seconds it just turns off (scanner), but if I put a breakpoint again - it works again (sic!).
public class ScanService extends Service
{
boolean blocked = false;
public ScanService()
{
}
#Nullable
#Override
public IBinder onBind(Intent intent)
{
return null;
// TODO: Return the communication channel to the service.
//throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
while(true)
{
if (!blocked)
{
String received = GlobalAccess.scan.scan(500);
if (received != null && !received.isEmpty())
{
//blocked = true;
}
}
else
{
try
{
Thread.sleep(500);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
}
Use a Service instead of AsyncTask. AsyncTasks are only designed to run with shorter background tasks. Keep in mind that whatever you run in a Service will execute on the main thread, so you should use a background thread within your Service.
Can you tell why the AsyncTask or IntentService is stopping? With an IntentService, with your while(true) loop, it should run indefinitely unless the app gets shut down for some reason.
Edit -
You need to do this to prevent your loop from blocking the main thread -
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while(true) {
// your code here
}
}
});
t.start();
}
I don't know why your Service is stopping. You need to be looking at your Logcat output. Set the filter to Error and you're crash should show up there.
Yes, there is an elegant solution for this type of thing. Use a service. In particular, the JobScheduler api is meant to handle this kind of stuff. Reason for using this is, as you stated, you have a long running task and you don't want to have to manage it dying. In addition, the JobScheduler is built to handle side effects of the OS. I assume that you want your job to run, but allow the app to perform its normal set of operations. Though, as a note, the API is smart in considering factors, such as battery levels, OS resources being used, wifi connectivity, so the jobs can be deferred.
The official documentation is here https://developer.android.com/reference/android/app/job/JobScheduler.html
An example of how to use it can be found here
https://code.tutsplus.com/tutorials/using-the-jobscheduler-api-on-android-lollipop--cms-23562
I am starting a new thread in my app's onCreate() method like so:
stepsLogger = new Runnable() {
while(!Thread.currentThread().isInterrupted()){
//my code
try {
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
loggerThread = new Thread(stepsLogger);
loggerThread.start();
While it is not interrupted, it is supposed to do its thing every 10 seconds.
I am logging some text at the start of the Runnable to see how often the code gets run. The first time I run the app it's fine, but every time i restart, the text gets logged more frequently which means that more threads are running.
I have tried to stop them in the onDestroy() method:
#Override
protected void onDestroy() {
super.onDestroy();
loggerThread.interrupt();
loggerThread = null;
}
How do I make sure that the old thread gets stopped whenever the app is restarted?
Thread.interrupt() will wake up a sleeping thread with an InterruptedException, so you're most of the way there already. I'd change your loop in the following way:
while (true) {
// some code
try {
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // restore the thread's interrupted flag
break;
}
}
The bit about re-interrupting the thread is subtle. You can read more about it in this post from one of the primary JVM architects: https://www.ibm.com/developerworks/library/j-jtp05236/
In case this link ever dies, the gist of it is that there can be multiple "recipients" of thread interruption. Catching the exception implicitly clears the thread's interrupted flag, so it's useful to set it again.
You could use a volatile boolean variable to determine when to stop. Something like this:
class WorkerRunnable implements Runnable {
private volatile boolean shouldKeepRunning = true;
public void terminate() {
shouldKeepRunning = false;
}
#Override
public void run() {
while (shouldKeepRunning) {
// Do your stuff
}
}
}
To start it:
WorkerRunnable runnable = new WorkerRunnable();
new Thread(runnable).start();
To stop it:
runnable.terminate();
I am writing a GUI game, and I want to wait for the game to finish, before returning the winner. However, since my Game manager class is separate from the class used to implement the game logic and detect a win, I want to know how I can make the game manager wait until the other class notifies it of a win, and then proceed to do other stuff. I have not really worked much with multithreading before, so I'm hoping someone could explain how I might achieve this.
Here is some relevant code from the GameManager class' main that I've tried:
...
Game game = new Game(mode);
String winner = game.getWinner();
...
And from the Game class:
public Game(Game.Mode mode){
this.board = new Board(7);
window = new BoardFrame(7, 7, mode, board); //Graphical interface
window.setVisible(true);
}
public String getWinner(){
synchronized(board.WINNER){
try {
board.WINNER.wait();
} catch (InterruptedException e) {}
}
return board.WINNER;
}
And the Board class:
public boolean update(int num){
if (isValidMove(CurrentPlayer, num)){
buttonClients.get(positions.get(CurrentPlayer)).clear();
positions.put(CurrentPlayer, num);
board[num] = 1;
buttonClients.get(num).performCallback(CurrentPlayer);
if ((WINNER = isGameFinished())!=""){
//Disable all further inputs
for (int i = 0; i<board.length; i++){
board[i] = 1;
}
synchronized (WINNER) {
WINNER.notify();
}
}
CurrentPlayer = (CurrentPlayer==PLAYER1)?PLAYER2:PLAYER1;
return true;
}
return false;
}
EDIT: So I have found the cause of the screen display issue, which is that all my code for the GameManager was in an EventQueue.invokeLater() block. I have taken it out of that block for now, and the screen is displaying properly now. However, when I play until the end, and the synchronized(WINNER) block is finally run, it seems like nothing happens? In other words, the game continues waiting on WINNER.
When I'm waiting on a thread, my favorite is using a CountDownLatch and Maybe using a Callable<V> and submitting it to a thread executor which returns a Future<V> which blocks until the thread is done.
public class Example {
ExecutorService executorService = Executors.newCachedThreadPool();
public void init(){
CountDownLatch latch = new CountDownLatch(1);
Future<Boolean> submit = executorService.submit(new Thread3());
executorService.execute(new Thread1(latch, submit));
executorService.execute(new Thread2(latch));
}
public class Thread1 implements Runnable{
private CountDownLatch latch;
private Future<Boolean> thread3;
public Thread1(CountDownLatch latch, Future<Boolean> thread3) {
this.latch = latch;
this.thread3 = thread3;
}
#Override
public void run() {
int i = 0;
try {
thread3.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
while (i < 50){
LockSupport.parkNanos(1000);
i++;
}
latch.countDown();
}
}
public class Thread2 implements Runnable{
private CountDownLatch latch;
public Thread2(CountDownLatch latch) {
this.latch = latch;
}
#Override
public void run() {
try {
latch.await();
System.out.println("We can continue");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Thread3 implements Callable<Boolean>{
#Override
public Boolean call() throws Exception {
int i = 0;
while (i < 50){
LockSupport.parkNanos(1000);
i++;
}
return true;
}
}
}
Good Resource:
http://tutorials.jenkov.com/java-concurrency/index.html
There's a couple of ways you could do this, but by far the neatest will be to use the observer pattern to create an event listener. The idea behind this pattern is to allow code to register an action to be performed when an event occurs, while isolating the event handler from the action it's going to invoke. Note that this solution doesn't require any multithreading.
If you really do want your GUI and game logic running on separate threads, seems like you're trying to implement the locking approach described here. There's a couple of things to watch out for:
The JVM can give you a waiting thread an InterruptedException at any time, for any reason. You should always check the condition that caused you to wait before you proceed.
Any time you're accessing state shared across threads, you need to make sure you are using synchronized and volatile appropriately.
Where you lock on WINNER, bear in mind this field can change. If Board is locked on WINNER and changes its value, a new thread entering Game would be free to obtain its lock before the Board block completes, because they're locking on different objects.
I want to pause and start thread untill variable standby.
But wait() and notify() is not work for me.
Is this a collect way to pause thread?
private boolean _threadIsWaiting = true;
private Object _specialObjectFromHttp;
public void methodToUse() {
Thread thread = new Thread(new Runnable() {
getParamsFromHttp();
while (_threadIsWaiting) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
convertObject(_specialObjectFromHttp);
)};
}
// Callback method (Thread wait for this.)
private void getParamsFromHttpCallBack(Object result) {
_specialObjectFromHttp = result;
_threadIsWaiting = false;
}
You could use an object to wait on, and call notify on it. I believe that to be the better approach (Actually, it is almost always better to utilize such a mechanism instead of sleeping and bool checking).
private Object _specialObjectFromHttp;
public void methodToUse() {
Thread thread = new Thread(new Runnable() {
getParamsFromHttp();
_specialObjectFromHttp.wait();
)};
}
// Callback method (Thread wait for this.)
private void getParamsFromHttpCallBack(Object result) {
_specialObjectFromHttp = result;
_specialObjectFromHttp.notifyAll();
}
In this case it seems plausible to just use the object that is being used in that control flow anyways, but you could also just add another object that has no purpose other than being waited for.
You could use a SynchronousQueue this will block until the information you need is provided. So in one thread call take, this will wait for a put on a different thread.
Both methods are blocking and no manual syncing is needed.
Is there a way to wait for all Runnables submitted to the SWT UI Thread via asyncExec(...) to finish?
Background:
I have a long-running operation, which among other things is triggering events that in turn submit Runnables to the SWT UI thread via the asyncExec(...) instance method of Display.
The progress of the long-running operation is shown in a ProgressMonitorDialog, and I would like to close the dialog only after the UI thread has finished executing the Runnables.
Changing the calls from asyncExec(...) to syncExec(...) is not an option, as the latter is not desired when the events are triggered from other contexts.
org.eclipse.swt.widgets.Display.readAndDispatch() will process an event from the event queue and return false if there are no more events to process. But you probably don't want to use this as it processes an event.
asyncExec(*) is a FIFO queue (although OS graphics events supersede the asyncExecs), so you could do most of your long-running op processing and then place a final asyncExec in the queue:
final boolean[] done = new boolean[1];
Runnable r = new Runnable() {
public void run() {
done[0] = true;
}
};
// now wait for the event somehow. The brute force method:
while (!done[0]) {
Thread.sleep(200);
}
In theory, all of the other asyncExecs spawned from your long running op will be finished by the time you get to the last one.
EDIT: potential other option
Create your own org.eclipse.core.runtime.jobs.Job and then join() it at the end:
public static class RefCountJob extends Job {
public RefCountJob() {
super("REF_COUNT");
}
int count = 0;
public void increment() {
count++;
}
public void decrement() {
count--;
}
#Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask("WAITING", IProgressMonitor.UNKNOWN);
while (count > 0) {
Thread.sleep(200);
monitor.worked(1);
}
monitor.done();
return Status.OK_STATUS;
}
}
To use it, increment() it every time you are going to fire off events, and have them decrement it when they're done (You have to make sure they decrement it no matter what exception is thrown :-)
RefCountJob ref = new RefCountJob();
// ... do stuff, everybody increments and decrements ref
ref.increment();
// ... do more stuff
ref.increment();
// at the end of your long-running job
ref.schedule();
ref.join();
Thanks, I ended up with the following. I think it is a pretty clean solution. By the way I would upvote your answer if I had enough reputation for that :)
public class SWTThreadingUtils
{
public static void waitForAsyncExecsToFinish(Display display)
{
Object waitObj = new Object();
display.asyncExec(new DummyRunnable(waitObj));
synchronized (waitObj)
{
try {
waitObj.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private static class DummyRunnable implements Runnable
{
private Object waitObj;
public DummyRunnable(Object waitObj)
{
this.waitObj = waitObj;
}
#Override
public void run()
{
synchronized (waitObj)
{
waitObj.notify();
}
}
}
}