Sprites not displaying after Thread to Runnable switch - java

I switched a thread from extending Thread to implementing Runnable (implementing Runnable is better practice, right?) so when I called surfaceCreated I went from:
public void surfaceCreated(SurfaceHolder holder) {
createSprites();
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
to:
public void surfaceCreated(SurfaceHolder holder) {
createSprites();
gameLoopThread.setRunning(true);
gameLoopThread.run();
}
as the start() method is not included in the Runnable interface. However, once I switched this, my sprites no longer displayed. This is the run() method:
public void run() {
Canvas c;
while (running) {
c = null;
try {
c = view.getHolder().lockCanvas();
synchronized (mPauseLock) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
synchronized (mPauseLock) {
while (mPaused) {
try {
mPauseLock.wait();
} catch (InterruptedException e) {
}
}
}
}
}
It gets called during both scenarios, but sprites only display when I call start() instead of directly calling run(). Could someone explain why this is?

You can't start a Thread by calling gameLoopThread.run() for a Runnable (or even by calling run() for a Thread).
You have to pass your Runnable instance to a Thread instance and call start() for that Thread.
For example :
public void surfaceCreated(SurfaceHolder holder) {
createSprites();
gameLoopThread.setRunning(true);
Thread t = new Thread(gameLoopThread);
t.start();
}

Related

delay inside while loop not working

i'm trying to make a delay inside while loop using Thread.sleep() method . here is my code :
new Thread(new Runnable() {
#Override
public void run() {
z=0;
while (z<45){
z++;
handler.post(new Runnable() {
#Override
public void run() {
time.setText(Integer.toString(45-z));
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
this code was working and suddenly a problem occurred . it started to make a delay less than one minute , sumtimes 500 ms and sumtimes less than that
Instead if using a different thread, Thread.sleep(), Handler and while loop you can try only with Handler like this,
private int timerCount = 0;
private static Handler myHandler = new Handler();
private void runVVRunnable() {
myHandler.postDelayed(runnable, 1000);
}
private Runnable runnable = new Runnable() {
#Override
public void run() {
timerCount++;
if ((time == null)) {
return;
}
if (timerCount <= 45) {
time.setText(Integer.toString(timerCount));
runVVRunnable();
}
}
};
#Override
protected void onDestroy() {
super.onDestroy();
myHandler.removeCallbacks(runnable);
}
you can just call runVVRunnable() it will do the same process which you are doing while loop
Just a guess but when sleeping/waiting on Java thread you need to try-catch InterruptedException.
This exception is thrown when "someone" calls interrupt() on your thread.
This will cause the thread to wake up from sleep early than expected.
Check if you catch InterruptedException before your thread terminated.

Synchronized, lock and wait blocking main UI thread

I have made a simple TaskManager trying to manage a Runnable queue that is needed for my project. However, with a simple scenario, adding a new Runnable blocks the calling thread (main UI thread).
It happens when you add a new task while a current task is not finished.
You can find below a scenario that reproduces it.
I don't clearly understand why, and how I could prevent this.
This is the task manager class :
public class TaskManager {
private Queue<Runnable> executionQueue;
private final Object lock = new Object();
public TaskManager() {
executionQueue = new LinkedList<>();
startListening();
}
public void executeAsyncWithCompl(Runnable runnable, CompletionHandler completionHandler) {
Runnable runnableWithCompl = new RunnableWithCompl(runnable, completionHandler);
executeRunnable(runnableWithCompl);
}
private void executeRunnable(Runnable runnable) {
synchronized (lock) {
executionQueue.add(runnable);
lock.notifyAll();
}
}
public void release() {
synchronized (lock) {
lock.notify();
}
}
private void startListening() {
Thread executionThread = new Thread(new Runnable() {
#Override
public void run() {
listenTasks();
}
});
executionThread.start();
}
private void listenTasks() {
synchronized (lock) {
while (true) {
try {
if(executionQueue.isEmpty()) {
lock.wait();
}
Runnable runnable = executionQueue.poll();
runnable.run();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
}
Here is the RunnableWithCompl class :
public class RunnableWithCompl implements Runnable {
private CompletionHandler completionHandler;
private Runnable runnable;
public RunnableWithCompl(Runnable runnable, CompletionHandler completionHandler) {
this.runnable = runnable;
this.completionHandler = completionHandler;
}
#Override
public void run() {
runnable.run();
if(completionHandler != null)
completionHandler.onFinish();
}
}
And the CompletionHandler interface :
public interface CompletionHandler {
void onFinish();
}
The scenario. Let's say you have an Activity with a spinner (to show UI is not blocked), and a button to trigger long tasks.
private TaskManager taskManager;
public void init() {
taskManager = new TaskManager();
launchLongTask();
}
private void onButtonClick() {
launchLongTask() ;
}
private void launchLongTask() {
Runnable longTask = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Log.d(TAG, "Launching long task");
taskManager.executeAsyncWithCompl(longTask, new CompletionHandler() {
#Override
public void onFinish() {
Log.d(TAG, "Long task finished");
}
});
}
The problem is in your startListening() implementation.
It holds the monitor to lock while it is executing tasks which means no other method can obtain the monitor while it is doing work.
This means release() and executeRunnable(...) will block until there are no more runnables queued.
It also means the thread might block if the thread running startListening() is notified before other threads, because it means those threads cannot continue until it releases the monitor.

Thread imageView update speeds up

I have a thread that is used to spin an imageview as other things happen in the background. It works great for spinning, but I've noticed as I turn it on and off (based on the spinningMain variable) the button starts to spin faster and faster and faster.
I'm unsure what the cause of this is as the thread is told to sleep every 100ms.
If it helps I also have another thread (runnable thread) which runs the main code in between, which I was wondering whether it was disrupting the thread?
The imageView update thread is:
final Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(100);
runOnUiThread(new Runnable() {
#Override
public void run() {
if (spinningMain == true) {
// update TextView here!
if (spinningAngleMain >= 360) {
spinningAngleMain = 0;
} else {
spinningAngleMain += 5;
}
imageButton.setRotation(spinningAngleMain);
}
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
And the Second thread is pretty much made as follows
new Thread(new Runnable() {
#Override
public void run() {
if (searchStateButton == true) {
//do all my stuff
}
My boolean variables are set to volatile if that helps as well.

I can't finish thread (runnable), how it is?

Thread thread;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_yippi);
final Handler hn=new Handler();
final TextView text=(TextView)findViewById(R.id.TextView01);
final Runnable r = new Runnable()
{
public void run()
{
text.settext("hi");
}
};
thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1750);
hn.post(r);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
thread.stop();}
The code here. I can not stop the runnable thread. Also, thread.stop() and thread.destroy() are deprecated. Can somebody help me? And also I don't understand how to stop the thread with the thread.interrupt() method. What's wrong?
The JavaDoc for Thread.stop() lists the following article as explanation for why stop() is deprecated: http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Most uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. To ensure prompt communication of the stop-request, the variable must be volatile (or access to the variable must be synchronized).
interrupt() is more suitable to stop some Thread from waiting for something, that is probably not coming anymore. If you want to end the thread, it's best to let its run() method return.
Create a boolean variable to stop the thread and use it in while(boolean) instead of while(true).
You can use Thread.interrupt() to trigger the InterruptedException within your thread. I've added code below that demonstrates the behavior. The mainThread is where your code would be and the timer Thread is just used to demonstrate delayed triggering of the interrupt.
public class Test {
public static void main(String[] args) {
final Thread mainThread = new Thread() {
#Override
public void run() {
boolean continueExecution = true;
while (continueExecution) {
try {
sleep(100);
System.out.println("Executing");
} catch (InterruptedException e) {
continueExecution = false;
}
}
}
};
mainThread.start();
Thread timer = new Thread() {
#Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Stopping recurring execution");
mainThread.interrupt();
}
};
timer.start();
}
}
You can use interrupt method of Thread to try stop a thread, like below code.
May be it`s useful to you.
public class InterruptThread {
public static void main(String args[]){
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
System.out.println("Thread is Runing......");
sleep(1000);
}
} catch (InterruptedException e) {
// restore interrupted status
System.out.println("Thread is interrupting");
Thread.currentThread().interrupt();
}
}
};
thread.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Will Interrupt thread");
thread.interrupt();
}
}

Animation Thread and EDT

As I discussed with Inerdia on the earlier post,
something is still strange When I'm in some JPanel (EDT for sure-I checked with the method check) and then I call some animation thread(the thread extend Thread) to start, inside the thread I'm not on EDT by check.
So I guess I should be because animation should be on EDT, so I wrapped the animate method with runnable and invokeAndWait(), but still got that in the animation thread I'm not on EDT, while calling to that code as I said earlier is on EDT, so, my invokeLater seems not to place that animation on EDT? why is that?
Relevant code(before wrapping the animate method with runnable and passing to invoke later:
So, being on a JPanel there is a line:
Animate(trainRailRoadTrack);
Implementation is:
void Animate(ArrayList<RailroadSquare> i_TrainRailRoadTrack) {
ArrayList<JPanelRailoadSquare> playerRailoadPanelsTrack = getRelevantRailroads(i_TrainRailRoadTrack);
new SuspendedAnimation(playerRailoadPanelsTrack).start();
jPanelBoard1.GetGameManager().EmptyPlayerSolution();
}
private class SuspendedAnimation extends Thread
{
private ArrayList<JPanelRailoadSquare> m_PlayerRailoadPanelsTrack;
public SuspendedAnimation(ArrayList<JPanelRailoadSquare> i_PlayerRailoadPanelTrack)
{
m_PlayerRailoadPanelsTrack = i_PlayerRailoadPanelTrack;
}
#Override
public void run()
{
m_IsAnimationNeeded = true;
for (JPanelRailoadSquare currRailoadSquare: m_PlayerRailoadPanelsTrack)
{
System.out.println("Is on Event dispatch thread: "+SwingUtilities.isEventDispatchThread());
currRailoadSquare.SetGoingTrain();
repaint();
try
{
Thread.sleep(150);
}
catch (InterruptedException e){}
currRailoadSquare.UnSetGoingTrain();
repaint();
}
}
Inside of SuspendedAnimation.run() you're not on the EDT. That's where you need to use invokeLater(), not when calling Animate():
#Override
public void run()
{
// We're outside the EDT in most of run()
m_IsAnimationNeeded = true;
for (JPanelRailoadSquare currRailoadSquare: m_PlayerRailoadPanelsTrack)
{
SwingUtilities.invokeAndWait(new Runnable() {
// The code that "talks" to Swing components has to be put on
// the EDT
currRailoadSquare.SetGoingTrain();
repaint();
});
// We want to keep sleeping outside the EDT.
try
{
Thread.sleep(150);
}
catch (InterruptedException e){}
SwingUtilities.invokeAndWait(new Runnable() {
currRailoadSquare.UnSetGoingTrain();
repaint();
}
}
}

Categories