Android Studio is not running AsyncTasks at the same time. Why? - android-asynctask

Suppose I have 2 AsyncTasks A and B.
Let A be:
public class A extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params){
int a = 1;
while(a < 10){
System.out.println(a);
for(int i = 0; i < 400000; i++){
//empty loop, just to spend time
}
a = a+2;
}
}
}
Let B be:
public class B extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params){
int a = 2;
while(a < 10){
System.out.println(a);
for(int i = 0; i < 400000; i++){
//empty loop, just to spend time
}
a = a+2;
}
}
}
I call both of them at my MainActivity like this:
...
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new A().execute();
new B().execute();
}
I expected the result to be some kind of merge (not perfect but somehow merged) between odds and evens, but I'm getting the whole result of A and after the whole result of B, like this:
1
3
5
7
9
2
4
6
8
Can anyone tell me if this is normal?
Is it possible to have multiple AsyncTasks running at the same time? (I think it is, because I know they are like threads)
If it is, what did I do wrong?
Thank you guys.

Android two AsyncTasks serially or parallel execution? - The second is freezing but the result is ok
You can opt into parallel execution by replacing execute() with executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR).
https://www.youtube.com/watch?v=HNcE6MLnuIw

Actually, no, that's not how AsyncTasks work. Assuming you're testing this on a device past Honeycomb, your asynctasks will queue up like they are in your example.
AsyncTask
Read the section titled "Order of Execution"
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.

Related

What cause thread unsafe but nothing shared across threads?

I am new to learn multi-thread programming. I am told that thread - unsafe problem is always caused by something shared across multi thread. That makes sense for me, however, that seems can not explain the issue in below code which appears nothing is shared across multi thread.
package test;
public class Outputer{
public void output(){
String name = "123456789";
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
package test;
public class TraditionalThreadSynchronized {
public static void main(String[] args) {
Outputer outputer = new Outputer();
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 50; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output();
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 50; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output();
}
}
}).start();
}
}
what I expected is that 123456789 should be seen intact. But sometimes, I can see the output in console as below.
... ...
123456789
123456789
123456789
123456789
123456789
123456789 // expected
112323456789 // unexpected
456789 // unexpetecd
123456789
123456789
123456789
123456789
123456789
... ...
I understand the root cause is that when one thread is executing code snippet below, its cpu time segment is over so thread is not able to finish execution. Another thread get cpu time segment then start to execute below code snippet but also possible to not finish the execution. then first thread again get cup time segment then continue to execute from where it was stopped.
In a word, I am aware that the root cause is below code snippet is not Atomic operation.
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
My fix is to surround with synchronized block as below. Now it reaches my expectation. Looks good.
synchronized(this) {
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
However, I still have some doubts which is currently haunted my mind. Somebody help !!!
Is the statement below true ? Always ?
the thread - unsafe problem is ALWAYS caused by something shared across my multi thread
I am asking because I don't see any data shared across threads in my example. The variable name is local variable, not a pass-in parameter or pass-out parameter (returned parameter). So name is thread safe.
If the statement is true, what is shared by threads ?
If the statement is false, any other situation can caused thread unsafe without sharing data across threads ?

Unity - TextMeshPro text object doesn't update

I have been using TMP objects in several instances in my game, but all of a sudden it decides not to work on a certain object.
public class BeforeRoundTimer : MonoBehaviour
{
public TextMeshProUGUI timer;
private Timer oneSecondTimer;
private int time = 5;
public void StartCountdown()
{
Debug.Log("One second timer");
oneSecondTimer = new Timer(1000);
oneSecondTimer.Elapsed += UpdateTime;
oneSecondTimer.Enabled = true;
oneSecondTimer.AutoReset = true;
oneSecondTimer.Start();
}
private void UpdateTime(object source, ElapsedEventArgs e)
{
if(time == 0)
{
oneSecondTimer.Stop();
return;
}
timer.text = $"{time}";
time--;
}
}
I know the text is updating because I put debug statements (I have since removed them) and they fired when UpdateTime() is called. I also viewed the inspector when the game was playing, and the text value would update in front of my eyes. The text only changes when I make some stylistic change to it (i.e. making it bold, changing the font asset, including changing the text itself). I have looked back to my old code and it basically runs the exact same way, but it actually changes in game.
Ok so after taking a break, I decided to find another way to call my method every second. Instead of using a Timer, I decided to use Unity's InvokeRepeating() function.
public class BeforeRoundTimer : MonoBehaviour
{
public TextMeshProUGUI timer;
private int count = 0;
public void StartCountdown()
{
InvokeRepeating(nameof(UpdateTime), 0, 1f);
}
private void UpdateTime()
{
if(count == 5)
{
CancelInvoke("UpdateTime");
return;
}
Debug.Log("Update Time");
timer.text = $"{5 - count}";
count++;
}
}
One thing I noticed when trying to use the Timer in a different way is that it was only updating the text value every other second. It ran 10 times (I put a Debug.Log() in UpdateTime()) but only changed the value every other time while not actually updating the TMP. You could replace nameof(UpdateTime) with "UpdateTime", but Visual Studio recommended that I use the former so I went with that.
In short: don't use timers, use Unity's InvokeRepeating() function because it works perfectly. It is actually very similar to JavaScript's setInterval() which I found interesting.

Why does only some of my objects get created using std::async

I have a loop that pushes back calls of std::async that are used to create objects in the pointed function and emplace them back to another vector. All the calls are pushed to the futures function and the results are ready when i used the VS debugger. However of the 507 calls, only 30 objects are actually created and i cant seem to pin point why.I have tried setting the launch policy to both async and defered but get the same result.
void load_sec_p(vector<Security>* secs, map<string, map<string, vector<daySec>>> *psa_timeline,security sec) {
Security tmp = Security(psa_timeline, &sec.tsymb, &sec.gicsInd);
std::lock_guard<std::mutex> lock(s_SecsMutex);
secs->emplace_back(tmp);
}
Above is the function being executed in the async call
below is the loop that pushes back the futures
for (auto& sec : security_list) {
m_SecFutures.emplace_back(std::async(load_sec_p,&async_secs, &psa_timeline, sec));
}
The following pictures show the watch of both variables after the above loop is completed and the entire future vectors is checked for completion.
I have tried creating the objects by just using a regular for loop and appending them synchronously but it simply just takes too long(2 hours and 11 minutes long). If anyone has any advice on alternatives or how to fix my vector problem it would be greatly appreciated.
The code that checks if all the futures is shown below:
bool done = false;
cout << "Waiting...";
do {
done = futures_ready(m_SecFutures);
} while (!done);
The function is
template<class T>
bool futures_ready(std::vector<std::future<T>>& futures) {
std::chrono::milliseconds span(5);
bool finished = false;
int pends = 0;
while (!finished) {
//allowing thread to sleep so futures can process a bit more and also
//so thread doesnt reach max cpu usage
std::this_thread::sleep_for(std::chrono::milliseconds(100));
for (auto& x : futures) {
if (x.wait_for(span) == std::future_status::timeout) {
++pends;
}
}
if (pends == 0) {
finished = true;
}
else {
pends = 0;
}
}
return finished;
}

OpenTK Integers Stop Changing Values after Window Open

I need to Have Integers that change in the Background while the GameWindow is Open in OpenTK i tested Some Things and It Totaly didn't work, after this code:
GameWindow polyWindow = new GameWindow(1024, 768);
polyWindow.Run(200);
the Folowwing Code:
if (Gamesets.Polygon.Playfield.timer == 2)
{
polyWindow.Close();
}
Does Not Execute, its Just a Basic Timer that Closes the Window after 2
Seconds, The Code for That is Here:
public static int timer;
public static int ms_timer;
public static void playfield()
{
while (true)
{
ms_timer = + ms_timer + 1;
System.Threading.Thread.Sleep(10);
Console.WriteLine(timer + "S"+ms_timer + "MS");
if (ms_timer == 100) { timer = timer + 1; ms_timer = 0; }
if (timer == 10)
{
}
and it Does Not Work after the GameWindow is Shown
Any code written after the GameWindow.Run() statement will not be executed until after the window has been closed. So the code checking if the time is equal to 2 will not run until polywindow.close() has already been executed or you manualy close the window.
Alternatively what you could do, is check the timer from within the Opentk window in the Update or Render methods and execute the Close() method there.
For example:
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
if (Gamesets.Polygon.Playfield.timer == 2)
{
Close();
}
}

Testing if random number equals a specific number

I know this might already have been answered, but all the places where i found it, it wouldn't work properly. I'm making a game in Greenfoot and I'm having an issue. So I'm generating a random number every time a counter reaches 600, and then testing if that randomly generated number is equal to 1, and if it is, it creates an object. For some reason, the object will be created every time the counter reaches 600. I'm somewhat new to Java so it's probably something simple.
import greenfoot.*;
import java.util.Random;
/**
* Write a description of class Level_One here.
*
* #CuddlySpartan
*/
public class Level_One extends World
{
Counter counter = new Counter();
/**
* Constructor for objects of class Level_One.
*
*/
public Level_One()
{
super(750, 750, 1);
prepare();
}
public Counter getCounter()
{
return counter;
}
private void prepare()
{
addObject(counter, 150, 40);
Ninad ninad = new Ninad();
addObject(ninad, getWidth()/2, getHeight()/2);
Fail fail = new Fail();
addObject(fail, Greenfoot.getRandomNumber(getWidth()), Greenfoot.getRandomNumber(getHeight()));
}
private int spawnCounter = 0;
private int invincibleCounter = 0;
Random random = new Random();
private int randomNumber;
public void act()
{
controls();
{if (spawnCounter > 500) {
spawnCounter = 0;
addObject(new Fail(), Greenfoot.getRandomNumber(getWidth()), Greenfoot.getRandomNumber(getHeight()));
}
spawnCounter++;
{if (spawnCounterTwo > 300) {
spawnCounterTwo = 0;
addObject(new APlus(), Greenfoot.getRandomNumber(getWidth()), Greenfoot.getRandomNumber(getHeight()));
}
spawnCounterTwo++;
}
if (invincibleCounter > 600)
{
int randomNumber = random.nextInt(10);
if (randomNumber == 1)
{
Invincible invincible = new Invincible();
addObject(invincible, Greenfoot.getRandomNumber(getWidth()), Greenfoot.getRandomNumber(getHeight()));
invincibleCounter = 0;
}
if (randomNumber == 2)
{
Storm storm = new Storm();
addObject(storm, Greenfoot.getRandomNumber(getWidth()), Greenfoot.getRandomNumber(getHeight()));
}
else
{
}
}
invincibleCounter ++;
}
}
private int spawnCounterTwo = 100;
public void controls()
{
if (Greenfoot.isKeyDown("escape"))
{
Greenfoot.stop();
}
}
}
I'm not getting errors as it is compiling fine, but when i run it i have issues. Any help? Thanks in advance!
This is only speculation, since I cannot see the rest of your code, but I suspect that you are seeding your random number generator with some constant number. So every time you run your program, the random number generator generates numbers in the same order. In order to confirm this, please show some more code.
Also, your brackets do not match, so at least please show enough code to have matching curly braces.
Are you sure it is created exactly when the counter hits 600? You're incrementing the counter every frame, and at the default ~30 fps speed, that's twenty seconds. Then every frame after that, you're getting a random integer and have a 10% chance to make an Invincible. But 10% chance will on average come up within ten frames, which is 1/3 of a second. Then the counter will reset and you'll wait twenty more seconds, then create an Invincible within the next second, and so on. If you want a 10% chance every 20 seconds, you need to reset the Counter in the else branch, as well as the "then" branch (or just reset it just inside your very first if).

Resources