I'm working on a plugin for a Minecraft server which automatically breaks melons for melon farms. It loops through all the blocks in all players' current chunks, and breaks the blocks that are melons. At first, I attempted to continuously call this function with a while loop in the onEnable method, however that caused the server to time/lag out. Without the while loop (only calling the function once from the onEnable), the plugin worked fine. Every time I reloaded the server, the function would run and all melons would be broken; so I decided to make a timer that would call the function every two minutes. For some reason, the server still times out, even with the timer, which I don't understand
Here's my code:
package me.spigot.itiurray.main;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin {
private long goTime = 0;
#Override
public void onEnable() {
getLogger().info("MelonDrop has been enabled.");
startBreakWithInterval();
}
private void breakMelons() {
for (Player player : Bukkit.getOnlinePlayers()) {
Chunk chunk = player.getLocation().getChunk();
int x = chunk.getX() << 4;
int z = chunk.getZ() << 4;
for (int xx = x; xx < x + 16; xx++) {
for (int zz = z; zz < z + 16; zz++) {
for (int yy = 0; yy < 256; yy++) {
Block block = chunk.getBlock(xx, yy, zz);
if (block.getType().equals(Material.MELON_BLOCK))
block.breakNaturally();
goTime = System.currentTimeMillis() + 120000;
}
}
}
}
}
private void startBreakWithInterval() {
boolean running = true;
while (running == true) {
if (System.currentTimeMillis() >= getGoTime())
breakMelons();
}
}
private long getGoTime() {
return goTime;
}
}
Edit: Here's what it currently looks like...
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
#Override
public void onEnable() {
getLogger().info("MelonDrop has been enabled.");
scheduledExecutorService.scheduleWithFixedDelay(() -> breakMelons(),
2, 2, TimeUnit.MINUTES);
}
Your code is stuck inside the while(running == true)
I suggest you to use a ScheduledExecutorService
For your time logic you should do the following
if(System.currentTimeMillis() - getGoTime() >= 120000)
{
breakMelons();
}
Then inside your break melons function just call it at the very end of your method outside your for loop and do the following
goTime = System.currentTimeMillis();
The goTime variable should really just be the time at which you last completed breaking all the melons. Then when you check that time against the current system time you check if the time difference between the current time and the last time you executed the melon function is greater than 120000ms.
A much clearer solution would look like this:
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
breakMelons()
}
}, 2, 2, TimeUnit.MINUTES);
This will be calling your method each 2 minutes. Also if you support java 8 then you could use the following syntax:
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
scheduledExecutorService.scheduleWithFixedDelay(() -> breakMelons(), 2, 2, TimeUnit.MINUTES);
The correct solution for this is to use a BukkitRunnable. You can see more examples at bukkit's documentation
JavaPlugin plugin; //Your plugin instance
Long timeInSeconds = 10;
Long timeInTicks = 20 * timeInSeconds;
new BukkitRunnable() {
#Override
public void run() {
//The code inside will be executed in {timeInTicks} ticks.
//After that, it'll be re-executed every {timeInTicks} ticks;
//Task can also cancel itself from running, if you want to.
if (boolean) {
this.cancel();
}
}
}.runTaskTimer(plugin, timeInTicks, timeInTicks); //Your plugin instance,
//the time to wait until first execution,
//the time inbetween executions.
Most other answers use BukkitRunnables and other native Java libraries. The best way to do this would be using a schedule task using a Runnable, not a BukkitRunnable.
Bukkit.getScheduler().scheduleSyncRepeatingTask(myPlugin, new Runnable() {
#Override
public void run() {
breakMelons();
}
}, 0, 2400);
The code below uses the recommended way of running a simple task repeatedly.
The reason you do not want to use BukkitRunnables the way that is recommended in another answer is because it creates a variable that is called and then left orphaned. This code uses an inline anonymous inner class in order to keep everything neat and tidy, while also giving you the same effect.
The only time you want to use a BukkitRunnable rather than just a normal Runnable, is when you have an intention of stopping the task in the future.
Related
This question already has answers here:
Java 8: Parallel FOR loop
(4 answers)
Closed 4 years ago.
Is there a easy way to parallelise a foreach loop in java 8 using some library stuff?
void someFunction(SomeType stuff, SomeType andStuff) {
for (Object object : lotsOfObjects)
object.doSomethingThatCanBeDoneInParallel(stuff, andStuff);
}
Multithreading is kinda painful and time consuming so i wonder if there is a simpler way to do the above using some library.
thanks.
edited in 3/06/2018
ExecutorServices is very handy indeed, I can't use shutdown() to wait because I run the thing every frame and create a new ExecutorServices every frame would be too expensive.
I ended up writing a class to parallelize a fori loop and I thought I share it with other newbies like me.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
public class ParallelForI {
public ParallelForI(int numberOfThread) {
NUMBER_OF_THREAD = numberOfThread;
executorService = Executors.newFixedThreadPool(NUMBER_OF_THREAD);
finished = new AtomicBoolean[NUMBER_OF_THREAD];
for (int i = 0; i < finished.length; i++)
finished[i] = new AtomicBoolean(true);
// true is better for waitForLastRun before any run.
}
private ExecutorService executorService;
private final int NUMBER_OF_THREAD;
private AtomicBoolean[] finished;
public void waitForLastRun() {
synchronized (this) {
/* synchronized outside the loop so other thread
can't notify when it's not waiting. */
for (int i = 0; i < NUMBER_OF_THREAD; i++) {
if (!finished[i].get()) {
i = -1;
try {
this.wait(); //
} catch (InterruptedException e) {
// do nothing and move one.
}
}
}
}
}
public void run(FunctionForI functionForI, final int MAX_I) {
for (AtomicBoolean finished : finished)
finished.set(false); // just started
for (int i = 0; i < NUMBER_OF_THREAD; i++) {
final int threadNumber = i;
executorService.submit(new Runnable() {
#Override // use lambda if you have java 8 or above
public void run() {
int iInitial = threadNumber * MAX_I / NUMBER_OF_THREAD;
int iSmallerThan;
if (threadNumber == NUMBER_OF_THREAD - 1) // last thread
iSmallerThan = MAX_I;
else
iSmallerThan = (threadNumber + 1) * MAX_I / NUMBER_OF_THREAD;
for (int i1 = iInitial; i1 < iSmallerThan; i1++) {
functionForI.run(i1);
}
finished[threadNumber].set(true);
synchronized (this) {
this.notify();
}
}
});
}
}
public interface FunctionForI {
void run(int i);
}
}
And this is the way to use it:
void someFunction(final SomeType stuff, final SomeType andStuff) {
ParallelForI parallelForI = new parallelForI(numberOfThread);
// swap numberOfThread with a suitable int
parallelForI.run(new ParallelForI.FunctionForI() {
#Override // use lambda if you have java 8 or above
public void run(int i) {
lotsOfObjects[i].doSomethingThatCanBeDoneInParallel(stuff, andStuff);
// don't have to be array.
}
}, lotsOfObjects.length); // again, don't have to be array
parallellForI.waitForLastRun(); // put this where ever you want
// You can even put this before parallelForI.run().
// Although it doesn't make sense to do that...
// Unlike shutdown() waitForLastRun() will not cause parallelForI to reject future task.
}
A solution could be to launch every task in a Thread as follows:
new Thread(() -> object.doSomethingThatCanBeDoneInParallel(stuff, andStuff)).start();
but this is not a relevant solution as Thread creation is costly, so there are mechanisms and tools to help you: the Executors class to build some pools.
Once you have the instance that will manage this, you provide it with tasks, which will run in parallel, on the number of threads you choose:
void someFunction(SomeType stuff, SomeType andStuff) {
ExecutorService exe = Executors.newFixedThreadPool(4); // 4 can be changed of course
for (Object object : lotsOfObjects) {
exe.submit(() -> object.doSomethingThatCanBeDoneInParallel(stuff, andStuff));
}
// Following lines are optional, depending if you need to wait until all tasks are finished or not
exe.shutdown();
try {
exe.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Use parallel streams. But this is not an universal solution.
For loops in java are inherently serial. There is no way to do such thing with them. With the introduction of streams though, you can parallelize the operations on a collection using them.
I want to do something that i am not sure can be done, and so far i haven't found any good answers to my question.
Here is my situation:
- I have implemented Timer as a Handler that has Runnable that is calling itself every 1s.
- I need now to implement a method like Timer.restart() that can restart my Runnable's params.
Here is my code so you can see it, and better understand what i have tried to achieve
private Runnable rStartCPRTick = new Runnable() {
public int seconds = 0;
public int minutes = 0;
public int hours = 0;
#Override
public void run() {
if(++seconds%60 == 0) //increases the time by one second
if(++minutes%60 == 0)
hours++;
mActivity.updateCPRTime(formatHHMMSS(hours,minutes,seconds));
mStartCodeHandler.postDelayed(this,1000); // tick again in 1s
}
public void restartCPRTick(){
seconds = 0;
minutes = 0;
hours = 0;
}
};
My runnable, i want to be able to call resetCPRTick() from outside Runnable and then call run that starts from the beggining.
Is such thing possible?
Thanks!!
Your runnable is a class. You can add any methods to it you want. Just keep a reference to it around and call a method that does it (to do this you probably want to make it a inner class rather than an annonymous class).
I'm working at the moment on a simple Chess A.I. (calculate possible future turns, rate them, chosse the best one, + some tricks so you don't have to calculate every single turn). The code is written in Java and I'm using Netbeans. To make the calculations faster, I use multithreading. The code works roughly like this:
Main function makes first some calculations and then starts 8 threads.
the threads execute the main-calculations
when they finish, they set a boolean value in a boolean array (finished[]) true. This array is in the "main Class" (if you call it like this), where also the main function is.
during all this time the main function is waiting and checking constantly if every value of the finished[] - array is true. If that is the case, it continues it's work.
Now I have a strange problem. The code works perfectly on my PC, but when I run the EXACT same code on my laptop, the main function won't continue its work, after all values of the finished[]-array are true. I already made some changes in the code, so I can try it with different numbers of threads, but the result is always the same.
I have totally no idea what's going on here and would really appreciate it, if someone of you had any answers and/or suggestions!
If you need any more Information just ask, I'll try my best. :)
(Sorry for possible grammar mistakes, english isn't my native language, but I'm trying my best. ;))
So I was asked to show some Code I used in the program:
(Perhaps first a warning, yes I am still a big Noob in Java and this is my first time I work with threads so don't be shocked if you see terrible mistakes I possibly made. xD)
The main Class looks something like this:
public class Chess_ai_20 {
static boolean finished[] = new boolean[8];
Distributor[] Distributors = new Distributor[8];
...
public static void main(String[] args) {
boolean testing=false;
...
//some calculations and other stuff
...
Distributors[0] = new Distributor(...., "0"); //the String "0" will be the thread name.
Distributors[1] = new ...
...
Distributors[7] = new Distributor(...., "7");
for (int i = 0; i < 8; i++) {
Distributoren[i].start();
}
testing=false;
while(testing==false){
if(finished[0]==true && finished[1]==true && ... && finished[7]==true){
testing=true; //That's the point where I get stuck I suppose
}
}
System.out.println("I made it!");
}
public static void setFinished(int i) {
finished[i] = true;
System.out.println("finished [" + i + "] = " + finished[i]);
System.out.println(Arrays.toString(finished)); //To check how many values already are true
}
}
Then we got of course the class "Distributor"
public class Distributor extends Thread {
Thread t;
String threadname;
boolean running=false;
...
Distributor(......, String s) {
threadname=s;
...
...
}
#Override
public void start() {
running=true;
if (t == null) {
t = new Thread(this,threadname);
t.start();
}
}
#Override
public void run() {
if(running){
...
//Do the main calculations etc.
...
//All the Calculations habe been done at this point
Chess_ai_20.setFinished(Character.getNumericValue(threadname.charAt(0))); //Set the value of finished[] true in the main class
running=false;
}
}
}
As others have mentioned, using a Future would be much simpler and easy to understand. Below is a snippet demonstrating how you could rewrite your code. Check out the code in action.
First, you write a Callable to define the task that you want to do.
public class MyCallable implements Callable<Boolean> {
#Override
public Boolean call() {
// Do some job and return the result.
return Boolean.TRUE;
}
}
And then, you submit this task to an Executor. There are a lot of Executors in JDK. You want to go through the Concurrency Tutorial first.
ExecutorService executor = Executors.newFixedThreadPool(Runtime
.getRuntime().availableProcessors());
List<Callable<Boolean>> callables = new ArrayList<>();
for (int counter = 0; counter < 8; counter++) {
callables.add(new MyCallable());
}
List<Future<Boolean>> futures = executor.invokeAll(callables);
for (Future<Boolean> future : futures) {
System.out.println(future.get()); // You'd want to store this into an array or wherever you see fit.
}
executor.shutdown();
Remember that the futures returned by the executor are in the same order as the Callables you submitted (or added) to the Collection (in this case, an ArrayList). So you don't need to worry about returning the index, an ID or even the name of the Thread (if you assigned one) to map the corresponding result.
I have the following class. The purpose of the class is to allow me to simulate a teletype/typewriter by displaying about ten characters a second.
The point of the CharacterLoopThread class is to look at the outputBuffer, and if there are any characters in it, invoke a runnable on the UI thread that pulls off the first character and plops it into the textView. The thread then sleeps for about 100ms. (There are some shenanigans here... while the teletype was amazing when I used it in 1979, it's a little slow for my tastes now. So every 10 characters, I reduce the delay slightly. When there are no more characters to display, I reset the delay to 100ms...)
I edited off the bottom of the class since it was not germane to my question.
What I have here seems to work well. However, does it work because of me or in spite of me? What are your preferred ways of writing Threads and Handlers?
public class MyActivity extends Activity {
private TextView textView;
private ScrollView scrollView;
private StringBuilder outputBuffer;
private Handler handler;
private CharacterLooperThread characterLooperThread;
(snip)
private class CharacterLooperThread extends Thread {
private boolean allowRun;
private Runnable run;
int effectiveCharacterDelay;
int characterCount;
public CharacterLooperThread() {
allowRun = true;
run = new Runnable() {
public void run() {
/**
* Don't do anything if the string has been consumed. This is necessary since when the delay
* is very small it is possible for a runnable to be queued before the previous runnable has
* consumed the final character from the outputBuffer. The 2nd runnable will cause an
* exception on the substring() below.
*/
if (outputBuffer.length() == 0) return;
try {
textView.append(outputBuffer.substring(0, 1));
scrollToBottom();
outputBuffer.deleteCharAt(0);
} catch (Exception e) {
toast(getMsg(e));
}
}
};
}
public void run() {
resetDelay();
while (allowRun) {
/**
* This if() performs 2 functions:
* 1. It prevents us from queuing useless runnables in the handler. Why use the resources if
* there's nothing to display?
* 2. It allows us to reset the delay values. If the outputBuffer is depleted we can reset the
* delay to the starting value.
*/
if (outputBuffer.length() > 0) {
handler.post(run);
reduceDelay();
} else {
resetDelay();
}
try {
Thread.sleep(effectiveCharacterDelay);
} catch (InterruptedException e) {
toast("sleep() failed with " + e.getMessage());
}
}
/**
* Make sure there's no runnable on the queue when the thread exits.
*/
handler.removeCallbacks(run);
}
public void exit() {
allowRun = false;
}
One idea is to use Handler.postDelayed to schedule the individual "keystrokes". You can either do this all at once, or have each keystroke Runnable schedule the next as it finishes; if processing gets behind schedule, the former approach will catch up as quickly as possible, while the latter will essentially push everything back to keep the same inter-keystroke delay.
It worries me to see one thread altering the StringBuilder while another reads it. (The StringBuilder class was a non-thread-safe successor to StringBuffer, which was written back in the day when folks thought making individual classes thread-safe was good design). If it doesn't occasionally do something unexpected, you're lucky, though not much can go wrong here. Using postDelayed, however, you might get rid of the background thread altogether.
As long as you are making anonymous Runnable classes, note that you can feed them arguments (as long you declare variable final). So I would tend to post one character at a time to each Runnable, like this:
long delay = 0;
for (int j = 0; j < outputBuffer.length(); ++j) {
final CharSequence s = outputBuffer.subSequence(j, j + 1);
handler.postDelayed(new Runnable() {
#Override public void run() {
textView.append(s);
scrollToBottom();
}
}, delay);
delay += 100; // or whatever
}
I'm writing a Java app which writes to excel sheet bunch of data, and it takes a while to do so.
I'd like to create something like writing out dots to screen like on Linux when you're installing something.
Is that possible in java?printing dots, while other thread actually does the writing to excel, then after its finished the one displaying dots also quits?
I'd like to print dots to console.
A variation to #John V. answer would be to use a ScheduledExecutorService:
// SETUP
Runnable notifier = new Runnable() {
public void run() {
System.out.print(".");
}
};
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// IN YOUR WORK THREAD
scheduler.scheduleAtFixedRate(notifier, 1, 1, TimeUnit.SECONDS);
// DO YOUR WORK
schedule.shutdownNow();
Modify the notifier object to suit your individual needs.
Its very possible. Use a newSingleThreadExecutor to print the dots while the other thread does the parsing. For example
ExecutorService e = Executors.newSingleThreadExecutor();
Future f = e.submit(new Runnable(){
public void run(){
while(!Thread.currentThread().isInterrupted()){
Thread.sleep(1000); //exclude try/catch for brevity
System.out.print(".");
}
}
});
//do excel work
f.cancel(true);
e.shutdownNow();
Yes, it is possible, you will want to have your working thread set a variable to indicate that it is working and when it is finished. Then create a thread by either extending the Thread class or implementing the Runnable interface. This thread should just infinitely loop and inside this loop it should do whatever printing you want it to do, and then check the variable to see if the work is done. When the variable value changes, break the loop and end the thread.
One note. Watch your processing speed. Use Thread.sleep() inside your loop if your processor usage goes way high. This thread should not be labour intensive. System.gc() is another popular way to make threads wait.
Not an elegant solution, but get's the job done. It prints 1, 2, 3, 1, 2... dots in a loop and terminates everything after 5 seconds.
public class Busy {
public Busy() {
Indicator i = new Indicator();
ExecutorService ex = Executors.newSingleThreadExecutor();
ex.submit(i);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i.finished = true;
ex.shutdown();
}
public static void main(String[] args) {
new Busy();
}
private class Indicator implements Runnable {
private static final int DOTS_NO = 3;
private volatile boolean finished = false;
#Override
public void run() {
for (int i = 0; !finished; i = (i + 1) % (DOTS_NO + 1)) {
for (int j = 0; j < i; j++) {
System.out.print('.');
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int j = 0; j < i; j++) {
System.out.print("\b \b");
}
}
}
}
}