Run Code Inside One Thread In Another - java

I am writing a Processing project (Processing is based on Java). I want to run the code inside one thread in another thread (the main thread).
//This method runs in the main thread
public void draw() {
}
//This is a callback that runs in a separate thread
void addTuioObject(TuioObject tobj) {
rect(0, 0, 20, 10);
}
The rect(0,0,20,10) does not run in the main thread (it is supposed to draw a rectangle on the screen). I suppose this is because it runs in a separate thread. How would I make this code run in the main thread?

Most common solution is to provide state variable and make draw() method to draw according to current state.
State variable may be as simple as single primitive type (boolean for example) or complex object.
Idea is that:
main thread (animation thread in processing) calls draw() for each frame, and draw() method uses state variable to paint screen.
other thread can modify state, but has nothing to do with drawing or pixels...
Consider 2 examples:
1) simple state (single boolean variable)
// state variable
private boolean shouldPaint;
void draw() {
background(0);
fill(200);
rect(10, 10, 30, 30);
if (shouldPaint) {
rect(50, 10, 30, 30);
}
}
// called in other thread
someMethod() {
shouldPaint = !shouldPaint;
}
2) more complex state
// state variable
private PVector[] vectors = new PVector[5];
private int index = 0;
void draw() {
background(0);
fill(200);
for (PVector v : vectors) {
if (v != null) {
rect(v.x, v.y, 10, 10);
}
}
}
// called by other thread
void someMethod() {
if (index >= vectors.length) {
index = 0;
}
// vector for current index value
PVector v = vectors[index];
if (v == null) {
vectors[index] = new PVector(index * 20, index * 20);
} else {
vectors[index].add(new PVector(30, 0));
}
index++;
}
Remember that draw() method is called 60 times per second (if default frame rate). Each draw() execution modifies screen (pixel) buffer. If you want to disapper unwanted objects from screen you should start draw() method with background(color) that clears whole buffer.

There are several ways to do this. Depending on what you actually want to achieve. If you're working with awt or swing your drawing code should actually not run in the main thread but in the awt thread instead. You can dispatch work to that thread for example using SwingUtils. If you really want to execute the code in another thread (e.g. main) you need to make sure that the target thread will be able to pickup new work e.g. from a queue.

Related

Extra Thread decreases FPS in LibGDX Java

I am using a Thread to do some calculations related to the app that need to be done simultaneously but this Thread causes the FPS to drop (logically) and I wanted to know how to resolve the issue as the Thread is not doing any heavy calculations at all. Here is the code where I implement the Thread and the Thread itself.
incrementMass = new IncrementMass();
incrementMass.start();
// I added some extra functionality to the InputProcessor but I assume that is irrelevant
if(InputProcessor.isButtonUp() && InputProcessor.getButtonLetGo() == RIGHT && !isJustPressed) {
isJustPressed = true;
try {
incrementMass.join();
} catch(InterruptedException e) {
e.printStackTrace();
}
planets.add(new Planet(10, m, mouseOnWorld2.x, mouseOnWorld2.y));
} else if(Gdx.input.isButtonJustPressed(RIGHT)) {
isJustPressed = false;
incrementMass.restart();
}
The Thread:
/**
* Thread to increment the mass in a while loop.
*/
public class IncrementMass extends Thread {
/**
* Increments the mass when started.
*/
#Override
public void run() {
super.run();
while(Gdx.input.isButtonPressed(Input.Buttons.RIGHT)) {
MainScreen.m += 100;
System.out.println(MainScreen.m);
}
}
/**
* Resets the mass so the whole thing starts over (for the creation of a new planet)
*/
public void restart() {
MainScreen.m = 100000;
}
}
All this is called in the render() function of my Screen by the way.
I have one idea as to what is causing this: Every frame I create a new Thread which is not optimal but everything else I tried failed to actually perform my calculations correctly. It definitely solves the FPS problem to have the initiation of the Thread and the ´start()´ function in the constructor of my Screen but that for some reason messes with the incrementing of the mass and makes it a fixed value: the value I reset it to in ´restart()´
I've been trying to solve this but I'm baffled so here I am.
As said in the comment, there was no function for isButtonJustUp() which made it not be able to run sequentially. Therefore I made a Thread so that it was sequential which is not a good implementation of Threads. I've come up with a solution:
if(Gdx.input.isButtonPressed(RIGHT)) {
m += 100;
} else if(InputProcessor.isButtonJustUp() && InputProcessor.getButtonLetGo() == RIGHT) {
planets.add(new Planet(10, m, mouseOnWorld2.x, mouseOnWorld2.y));
m=0;
}
I haven't made isButtonJustUp() yet but it is the best way rather than implementing an unnecessary Thread.

Why is the inventory updating?

I am using Bukkit API 1.8 with Java 7.
I have a repeating task that loops through all the players on the server and sets their armor randomly to either leather, chainmail, etc...
When I use the method setHelmet,setChestplate, etc... I update their inventory like usual, but since this task is running every 6 ticks, it runs fast. Therefore, when a player tries to fire a bow, the bow resets its power every time this task runs.
Since I knew it was a problem with updating the inventory, I tried removing the updateInventory method.
After doing this the armor still got put on and changed, but the bow was still being reset every time the task was ran.
How would I keep the bow from resetting while still keeping the task running?
My code:
#SuppressWarnings("deprecation")
public static void repeatEffect()
{
main.getServer().getScheduler().scheduleAsyncRepeatingTask(main, new Runnable()
{
#Override
public void run()
{
for(Player o : Bukkit.getOnlinePlayers())
{
Material M1 = Material.WOOL;
int num = rainbow.get(o.getName());
if(num==1)
{
M1 = Material.LEATHER_HELMET;
}
else if(num==2)
{
M1 = Material.CHAINMAIL_HELMET;
}
else if(num==3)
{
M1 = Material.GOLD_HELMET;
}
else if(num==4)
{
M1 = Material.IRON_HELMET;
}
else if(num==5)
{
M1 = Material.DIAMOND_HELMET;
}
rainbow.put(o.getName(), num+1);
if(rainbow.get(o.getName())>5)
{
rainbow.put(o.getName(), 1);
}
ItemStack rrhelm = createItemStack(M1, 1, "§a§lR§b§la§c§li§d§ln§e§lb§f§lo§a§lw §c§lH§d§le§e§ll§f§lm§a§le§b§lt", "§7Very special piece of armor");
o.getInventory().setHelmet(rrhelm);
}
}
}
, 6, 6);
}
If changing armour resets the players bow, you could work around it by only changing the armour of players who are joining, not wielding a bow or just after an EntityShootBowEvent.
To see if the player is wielding a bow, use:
org.bukkit.Bukkit.entity.Player player = ...;
boolean hasBowEquiped = player.getEquipment().getItemInHand().getData().getItemType().equals(Material.BOW);
After testing this some more, the only way I was able to reproduce the bow complication was by calling the deprecated updateInventory() method which you said you removed. I'm fairly certain that you still have this method somewhere in your code because I can't find anything else that would cause the bow to act this way (I was still able to fire the bow but the animation looks glitchy and the power of the arrow is sometimes incorrect).
The only difference between my code is that I used new ItemStack(M1) instead of your createItemStack() method to instantiate the helmet (also tried changing name, lore and amount). I was still able to shoot a bow just fine. Could the resetting of the bow/inventory have something to do with your createItemStack method?
There's no reason why you should be running this task asynchronously. You're accessing the Bukkit API from an asynchronous task or different thread which is a big no-no and can cause all kinds of tricky problems. Use the scheduleSyncRepeatingTask method to run the task in the same thread.
For simplicity's sake I randomly set a single armor slot (also tried all four) to either leather or iron every 6 ticks. Didn't seem to interfere with the bow. Could we see your code? Here is mine:
public void onEnable() {
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
public void run() {
for (World world : Bukkit.getWorlds()) {
for (Player player : world.getPlayers()) {
if (Math.random() < 0.5) {
player.getInventory().setBoots(new ItemStack(Material.IRON_BOOTS));
} else {
player.getInventory().setBoots(new ItemStack(Material.LEATHER_BOOTS));
}
}
}
}
}, 0, 6);
}

Java paint 'stuttering' -list concurrency

One of my applications paints objects to a screen by reading an array List:
simple code summary:
#Override
public synchronized void paintComponent(Graphics g) {
for(Object gO:paintList) {
g.drawImage( gO.getObjImage(), gO.getXLoc(), gO.getYLoc(), outer.getTransparent(), null);
}
}
The problem is I add more objects every time the user clicks the mouse, so if if the user clicks fast enough, I can cause the program painting to stutter since it cannot read while it is writing (the arrayList is synchronized). What is the common practice developers use to deal with this concurrency issue?
edit: here is the code that calls the repaint:
byte ticks = 0;
while(true) {
currentTime = System.nanoTime();
if(ticks == 25) {
drawPanel.repaint();
ticks = 0;
} else if (ticks%5 == 0) {//if ticks is a multiple of 5 (5,10,15,...)
drawPanel.operations();
ticks++;
} else if(ticks < 25) {
ticks++;
}
try {
/*
Refer to: 'http://stackoverflow.com/questions/1036754/difference-between-wait-and-sleep'
on differences between Thread.sleep() and wait()
*/
wait(1);//old timings: (long)(refreshRate*1000)
} catch (InterruptedException ex) {
Logger.getLogger(DeathWish.class.getName()).log(Level.SEVERE, null, ex);
}
//Debugging
//System.out.println(ticks);
currentTime = System.nanoTime();
*where operations() calculates changes in 'paintable' object's properties, removes objects that meet certain conditions and adds new objects to the paint list. Logically to me, the adding and writing should be separated?
I can post the operations() method, if there isn't enough information, but I'm trying not to post huge sections of code so it is easier to interpret.
I guess you're getting things a bit wrong with synchronization :
ArrayList is a list implemented without synchronization
A synchronized method means that only 1 Thread at a time can access the method, but the variables inside your function are not synchronized at all
What you want, is to have your list temporary synchronized.
You could do something like that :
#Override
public void paintComponent(Graphics g) {
synchronized(paintList) {
for(Object gO:paintList) {
g.drawImage( gO.getObjImage(), gO.getXLoc(), gO.getYLoc(), outer.getTransparent(), null);
}
}
}
and in the code adding objects yo your list do somewhat the same.
EDIT from here :
If you want to remove all the concurrency problems between the add thread and the paint Thread, here's how you could do :
in the method to add images :
public synchronized void addImage(...) {
Something newImage = .....
List<Something> newPaintList = new ArrayList<>(paintList.size() + 1);
newPaintList.addAll(paintList);
newPaintList.add(newImage);
paintList = newPaintList;
}
And in the paint method, remove the synchronization part.
#Override
public void paintComponent(Graphics g) {
for(Object gO:paintList) {
g.drawImage( gO.getObjImage(), gO.getXLoc(), gO.getYLoc(), outer.getTransparent(), null);
}
}
With this, you won't have any concurrency between the reads and the writes, since the only operation done on paintList is reads.
The addImage should be synchronized to avoid two different Threads adding images at the same time, which could make one addImage ignored.

In Java, why is my multithreading not working?

At first I did this:
public SpaceCanvas(){
new Thread(new Runnable () {//this is the thread that triggers updates, no kidding
int fcount = 0;
#Override
public void run() {
System.out.println("Update thread started!");
while(!Thread.interrupted()){
fcount++;
while(players.iterator().hasNext()){
players.iterator().next().update(fcount);
}
while(entities.iterator().hasNext()){
entities.iterator().next().update(fcount);
}
System.out.println("About to paint");
repaint();
System.out.println("Done with paints");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
players.add(new LocalPlayer(0, 9001, 0, 0, 0, 0, this, null));
}
in the initializer of a thing I call a SpaceCanvas.
However, that doesn't allow the canvas, and therefore the applet it is within, to be created, because the Thread doesn't actually run asynchronously. Then, I replaced ".start()" with ".run()" and the thread only ran once, but the SpaceCanvas initialized perfectly.
What did I do wrong, and how do I fix this?
I'm not sure this sort of code works the way you expect it to:
while(players.iterator().hasNext()){
players.iterator().next().update(fcount);
players.iterator() gets a new iterator for the players collection. If there are 0 items in the collection then it will be false but if there are any items, you will be in an infinite loop, creating a new iterator each time. The iterator() call inside of players generates another new iterator object as well.
I think you should doing something like:
Iterator iterator = players.iterator();
while (iterator.hasNext()) {
iterator.next().update(fcount);
}
This is the same with your entities loop as well. A better pattern (as of Java 5) is to use the for loop:
for (Player player : players) {
player.update(fcount);
}
Also, if multiple threads are accessing these collections, they have to be somehow synchronized. You can either use a concurrent collection or you have to make sure every access (read and write) is within a synchronized block.
synchronized (players) {
for (Player player : players) {
player.update(fcount);
}
}
...
// down in the outer thread
synchronized (players) {
players.add(new LocalPlayer(0, 9001, 0, 0, 0, 0, this, null));
}
Obviously the entities will need to be synchronized in the same manner.
In this millennium, use Swing (JApplet/JPanel) rather than AWT (Applet/Canvas)
When using Swing, establish a Swing Timer that calls repaint() every 500 msec.
(When using Swing/Timer) Don't call Thread.sleep(n) on the EDT (Event Dispatch Thread).
..can you draw on a JPanel?
Sure thing. To do so, override the paintComponent(Graphics) method. You might also extend a JComponent and do the same, but there are some quirks to dealing with a JComponent that make the JPanel the better choice to extend.
On the other hand, there is another approach entirely.
Create a BufferedImage of the size required for whatever custom graphic is needed.
Add the image to an ImageIcon.
Add the icon to a JLabel.
Add the label to the GUI.
On each Timer action.
Call image.getGraphics() to obtain the drawing surface.
Replicate what you might have done in paint() or paintComponent()
(If needed) erase all previous drawing.
Draw the current custom rendering.
dispose() of the Graphics instance of the image.
call label.repaint()

Correct use of wait()/notify() for a Tetris game

I’m writing a Tetris-like game for Android and I’m trying to implement the “real-time part”. I have something which seems to work, but I want to be sure that my implementation is correct.
What I want is:
The shapes are going down at a fixed rate (say that I want to wait n milliseconds each time the y of the shape is decremented)
The player can drop the shape at any time and the timer waiting for the n milliseconds must then be immediately interrupted and start again only for the next shape
When the shape is droped or when the shape cannot go down anymore, the game waits m milliseconds before creating another shape
The system have to be able to stop the thread at any time
What I am doing is the following (the system can stop the thread with interrupt()):
class TetrisThread extends Thread {
private int n = 3000; // for testing purposes, in the real game n will be smaller ;)
private int m = 1000;
#Override
public void run() {
doDraw();
while(!interrupted())
{
try {
synchronized (this) {
wait(n);
}
doPhysics();
doDraw();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
// This method is the one which will drop the shape, it is called from another thread
synchronized public boolean onTouch([…]) {
[…]
// The shape has to be dropped
dropShape();
notify();
[…]
}
private void doPhysics() throws InterruptedException {
[…]
// The shape cannot go down or has been dropped
sleep(m);
createNewShape();
[…]
}
}
In particular, the part synchronized(this) { wait(n); } looks funny because if I understand correctly this will take a lock on this and release it immediately.
But wait() requires to be used in a synchronized(this) block (why?) and I cannot either synchronize the whole run() method, because then if I try to drop three times the shape during the sleep(m) call, then the three next shapes will be automatically dropped (which is not what I want).
Does this seem correct to you?
Do you have any correction, advice, or remark?
Thank you :-)
The wait() method is used to make the current running thread to wait the object invoking wait() invoke notify() (in this case this). The synchronized(this) part needed to make sure only one thread at that time accessing this.
You can't synchronize the whole run() method, because the run() is from the parent (Thread) class and the parent didn't use synchonized in the declaration.
I don't know how to solve your other problem because I don't get how your program works right now.

Categories