I am trying to run a method inside a runnable from an API. I am not quite sure how to do this.
public void startRepeatingTask(JavaPlugin plugin,final String taskName,
Long repeatTime, Callable<T> func){
task = null;
task = Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
#Override
public void run(){
if(!tasks.containsKey(taskName)){
tasks.put(taskName, task.getTaskId());
}
}}, repeatTime);
}
I want the method to be inside the run() function! Help please!
Related
I did lot of google but I could not find how to return value from Runnable interface using FutureTask.
I need to return outcome of run method using FutureTask, I know that same can be archived using Callable Interface but how it can be done using Runnable Interface.
FutureTask constructor accepts second parameter for return value.
public FutureTask(Runnable runnable,V result)
How to assign outcome of run() method to V result.
FutureTask<String> futureTask=new FutureTask<String>(new Runnable() {
#Override
public void run() {
String outcome="Task Completed Successfully";
}
},null);
I am using
ExecutorService exec = Executors.newSingleThreadExecutor(new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
Future fs = exec.submit(new Callable() {
public Object call() throws Exception {
return null;//yourObject
}
});
fs.get();//your object
The null value in your call is the return value. To have it return "Task Completed Successfully", you'd need:
FutureTask<String> futureTask=new FutureTask<String>(new Runnable() {
#Override
public void run() {
}
}, "Task Completed Successfully");
This is clearly not very useful if you want the Runnable to compute a result, however.
Use a Callable, instead.
I have created interface with one method:
public interface ResultCallback {
void onResult(String message);
}
And I have object with method that has interface as parameter:
public class Command() {
public void methodWithCallback(int param1, String param2, ResultCallback callback) {
// There are some calculations
callback.onResult(param2);
}
}
Then In my Main Java file I write this:
public class Main() {
public static void main(String[] args) {
Command c = new Command();
c.methodWithCallback(int 0, "SOME STRING", new ResultCallback() {
#Override
public void onResult(String str) {
// work with str
outsideMethod(str);
}
});
}
public void outsideMethod(String str) {
// some code
}
}
Does this code can be considered as async? And is it safe to call outsideMethod to handle params?
As said, it is not async. For the call to be async the method should execute on another thread.
You can't call outsideMethod since it's called from a static method. You need an instance of main to be able to call outsideMethod. If it is safe or not depends on what the code is doing.
One way to make it async is the following:
public class Command {
private ExecutorService iExecutor;
public Command(ExecutorService executor) {
iExecutor = executor;
}
public void methodWithCallback(final int param1, final String param2, final ResultCallback callback) {
iExecutor.execute(new Runnable() {
#Override
public void run() {
// There are some calculations
callback.onResult(param2);
}
});
}
}
You have to know what you're doing if using threads. Things have to be thread safe etc depending on how you are doing stuff. To run Command on a single thread create a single thread Executor and pass same Executor to all Commmand, like so:
ExecutorService executor = Executors.newSingleThreadExecutor();
Command command1 = new Command(executor);
Command command2 = new Command(executor);
I have days trying to solve this but I can't, and the solution to this is to go to StackOverflow :D. Happens that I'm working with libgdx (library to make games) and to query code in Android is through the Handler class, running a Runnable and I don't really know how it works.
Basically what I want is to retrieve a value from Runnable. Using the Handler class with callbacks or something like that
I have to say that I don't really understand multithreading programming, and I saw several methods in Handler class, but I can't understand how it works (messaging, callbacks, etc.)
public class ActionResolverAndroid implements ActionResolver {
Handler handler;
Context context;
public ActionResolverAndroid(Context context) {
handler = new Handler();
this.context = context;
}
public boolean checkAndroidData(){
final boolean[] result = {false};
handler.post(new Runnable() {
#Override
public void run() {
// Android code here
// I need know the value of this variable
result[0] = true;
}
});
return result[0];
}
Thanks a lot for reading.
cheer
pd) I can't using Runnable .join() or Callable<>
When you post a Runnable to the Handler, that code will RUN in the MainThread (the one that you can touch your views).
doing:
public boolean checkAndroidData(){
final boolean[] result = {false};
handler.post(new Runnable() {
#Override
public void run() {
// Android code here
// I need know the value of this variable
result[0] = true;
}
});
return result[0];
}
Will make the result[0] being always false cause the Runnable would not runned yet.
The way you can notify yourself about the conclusion would be creating a Interface listener that you can notify when the Runnable ends.
Consider the following interface implementation:
public interface Listener<T> {
void on(T arg);
}
Working with a Listener would be waiting the response in the listener instead of the return value of a method, so the method above would be like:
public void checkAndroidData(Listener<Boolean> onCompleteListener){
handler.post(new Runnable() {
#Override
public void run() {
onCompleteListener.on(true);
}
});
}
And to call, you would pass a instance and wait for the response, like:
void onCreate(Bundle s){
super.onCreate(s);
checkAndroidData(new Listener<Boolean>(){
public void on(Boolean result){
Toast.makeText(result, Toast.LENGHT_LONG).show();
}
});
}
Well, this is a example, and in this case both code will run in the MainThread, this example doesnt cover multithreading, but about how to listen to the event that you started.
But the solution applies to multithreading if done in that context.
You can use a callback:
public interface RunnableListener
{
void onResult(boolean[] result);
}
// a field in your class
private RunnableListener runnableListener;
private void someMethod()
{
new Handler().post(new Runnable()
{
#Override public void run()
{
runnableListener.onResult(new boolean[]{true});
}
});
}
I am attempting to pass the return value from scheduling a task into an anonymous class, but I am running into trouble. If I set the return value to a final variable, it says it is not initialized:
/* Not initialized */
final BukkitTask task = Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
public void run() {
/* irrelevant code */
task.cancel();
}
}, 0L, 20L);
I have also attempted passing a variable by calling a method within the anonymous class, however it changes the return type to void and therefore I cannot pass a proper value:
BukkitTask temp = null;
/* Returns void */
temp = Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
private BukkitTask task;
public void initTask(BukkitTask task) {
this.task = task;
}
public void run() {
/* irrelevant code */
task.cancel();
}
}.initTask(temp), 0L, 20L);
How can I pass a returned value into an anonymous class within the code?
You can define this class
class Box<T> {
public volatile T value;
}
and use it like this:
final Box<BukkitTask> taskBox = new Box<BukkitTask>();
taskBox.value = Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
public void run() {
/* irrelevant code */
taskBox.value.cancel();
}
}, 0L, 20L);
However, taskBox.value in run could still be null depending on when runTaskTimer actually executes the runnable.
My idea, which might sound stupid, would be to create a global variable to which you assign the return value. Then, have a static method that would return this value to you in the anonymous class.
I seem to have figured out an answer rather quickly!
You can change the return type of the init method, and then it will return the proper values for the code!:
BukkitTask task = null;
task = Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
private BukkitTask task;
public Runnable initTask(BukkitTask task) {
this.task = task;
return this;
}
public void run() {
/* irrelevant code */
task.cancel();
}
}.initTask(task), 0L, 20L);
I am not sure what are you trying to do. Would Callable instead of Runnable solve the problem? http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html
see this example
public static void main(String[] args) {
final Object objectA[] = new String[1];
new Thread(new Runnable() {
private A refA = null;
public void run() {
objectA[0] = "Hello World or your object";
}
}).start();;
while (objectA[0] == null){
}
System.out.println(objectA[0]);
}
suppose we have these classes and read the comments
class Work {
void doWork(){ }
void commit(){}
}
class MyRunable implements Runnable {
run(){
Work work=new Work();
work.doWork();
//i can't write work.commit() here, because sometimes i want Thread runs both methods
//and sometimes runs only doWork()
}
}
class Tasks{
main(){
MyRunable myRunable=new MyRunable();
Thread t=new Thread(myRunable);
t.start();
//suppose now i need to call commit() method by the same thread (t)
//how can i do that
}
}
also i don't want to use constructor to determine if i want to call both method or not
You could try using a thread pool with a single thread and keep enqueuing methods as needed:
class Tasks {
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
final Work work = new Work();
exec.submit(new Runnable() {
public void run() {
work.doWork();
}
});
// later
exec.submit(new Runnable() {
public void run() {
work.commit();
}
});
}
}
This way, both methods will be executed in a sequence by the same thread, but separately.
Add parameter to your class MyRunnable. Call this parameter "runingMode". It could be an enum:
enum RunningMode {
DO_WORK {
public void work(Work work) {
work.doWork();
}
},
COMMIT {
public void work(Work work) {
work.commit();
}
};
public abstract void work();
}
Now your class MyRunnable should have list of modes:
class MyRunable implements Runnable {
private Collection<RunningMode> modes;
MyRunable(Collection<RunningMode> modes) {
this.modes = modes;
}
}
Implement run() method as following:
Work work=new Work();
for (RunningMode mode : modes) {
mode.work(work);
}
work.doWork();
Create instance of your class passing to it the mode you currently need:
MyRunable myRunable=new MyRunable(Arrays.asList(RunningMode.DO_WORK, RunningMode.COMMIT));
You could use an anonymous class.
final boolean condition = ...
Thread t = new Thread(new Runnable() {
public void run() {
Work work=new Work();
work.doWork();
if(condition)
work.commit();
}});
t.start();