I have a sub class of RecursiveTask which contains a Runnable object and should execute it.The problem is that the code inside the run method never gets reached although I use ForkJoinPool.execute in order to not block the main thread.
public class test {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
Display.getDefault().syncExec(new Runnable() {
#Override
public void run() {
System.out.println("lo");
}
});
}
};
ATLockTask t = new ATLockTask();
t.runnable = r;
new ForkJoinPool().execute(t);
}
}
public class ATLockTask extends RecursiveTask<Object>{
public Runnable runnable;
#Override
protected Object compute() {
try {
runnable.run();
} catch (Exception e) {
logger.catching(e);
}
return null;
}
}
Related
So I have a loop class that is basically as follows:
public class Loop extends Thread {
private boolean running;
public Loop() {
running = false;
}
public void run() {
while(running) {
//Do stuff
}
}
public void setRunning(boolean b) {
running = b;
}
}
What I'd like to know is whether or not it is possible to store methods. For example the class could look like this instead.
public class Loop extends Thread {
private boolean running;
private Method method;
public Loop() {
running = false;
}
public void run() {
while(running) {
if(method != null)
method.callMethod();
}
}
public void setRunning(boolean b) {
running = b;
}
public void setMethod(Method m) {
method = m;
}
}
Is anything like this possible?
I assume you want this functionality in Java 6, so you can use interface and anonymous class.
Interface code:
public interface Listener {
void callMethod();
}
Your Thread:
public class Loop extends Thread {
private boolean running;
private Listener listener;
public Loop() {
running = false;
}
public void run() {
while(running) {
if(listener != null)
listener.callMethod();
}
}
public void setRunning(boolean b) {
running = b;
}
public void setListener(Listener listener) {
this.listener = listener;
}
}
Set Listener:
Loop loop = new Loop();
loop.setListener(new Listener() {
#Override
public void callMethod() {
// Do stuff
}
});
This will work for your usecase. If you want to save methods and pass methods as data, you have to either use Java 8 (not supported on all Android API levels) or Kotlin.
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.
I'm trying to create a class that sequentially performs the Bluetooth tasks without user intervention aside from starting the process. In this class an external event calls the overridden method "executeCentral" from there it calls setup() to enable and request permissions. If they complete successfully the initialize() method is called and waits for one second before calling the Bluetooth initialize() which is executed in the EDT. If it runs without exception it calls startScanning() which also waits 1 second before calling Bluetooth startScan() in the EDT. After scanning has started it waits 10 seconds before calling Bluetooth stopScan() in the EDT.
I recreated the project for a clean setup and used the "downloader" in the Codename One Settings. It compiles successfully and runs, but reports an exception on "Bluetooth not initialized"
Any idea on what I am doing wrong? I'm under the impression that all calls must be done in the EDT.
The single form BTDemo compiles and executes each task as a separate user initiated event.
public class UITaskBluetoothEx extends com.crumptech.library.mobile.ui.tasks.UITaskBluetooth {
protected Bluetooth bt = new Bluetooth();
protected Map devices = new HashMap();
public UITaskBluetoothEx() {
super();
}
#Override
public String getReplacement() {
return "UITaskBluetoothEx";
}
protected void showDebug(String message) {
Display.getInstance().callSerially(new Runnable() {
#Override
public void run() {
UIApplication.showDebug("UITaskBluetoothEx " + message);
completed(result(false));
}
});
}
#Override
protected void executeCentral() {
bt = new Bluetooth();
try {
setup();
initialize();
} catch (Exception e) {
showDebug(e.getMessage());
}
}
protected void setup() throws IOException {
if (!bt.isEnabled()) {
bt.enable();
}
if (!bt.hasPermission()) {
bt.requestPermission();
}
}
protected void initialize() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Display.getInstance().callSerially(new Runnable() {
#Override
public void run() {
try {
if (!bt.isInitialized()) {
bt.initialize(true, false, "ShopMyLocalStores");
}
startScanning();
} catch (Exception e) {
showDebug(e.getMessage());
}
}
});
}
}, 1000);
}
protected void startScanning() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Display.getInstance().callSerially(new Runnable() {
#Override
public void run() {
try {
if (!bt.isScanning()) {
bt.startScan(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
try {
JSONObject res = (JSONObject) evt.getSource();
if (res.getString("status").equals("scanResult")) {
if (!devices.containsKey(res.getString("address"))) {
devices.put(res.getString("address"), res);
}
}
} catch (JSONException e) {
}
}
}, null, true, Bluetooth.SCAN_MODE_LOW_POWER, Bluetooth.MATCH_MODE_STICKY, Bluetooth.MATCH_NUM_MAX_ADVERTISEMENT, Bluetooth.CALLBACK_TYPE_ALL_MATCHES);
stopScanning();
}
} catch (Exception e) {
showDebug(e.getMessage());
}
}
});
}
}, 1000);
}
protected void stopScanning() {
try {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Display.getInstance().callSerially(new Runnable() {
#Override
public void run() {
try {
if (bt.isScanning()) {
bt.stopScan();
}
} catch (Exception e) {
showDebug(e.getMessage());
}
showResults();
}
});
}
}, 10000);
} catch (Exception e) {
}
}
protected void showResults() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Display.getInstance().callSerially(new Runnable() {
#Override
public void run() {
String text = "";
Iterator it = devices.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
text += (pair.getKey() + " = " + pair.getValue() + "\r\n");
}
UIApplication.showDebug(text);
completed(result(true));
}
});
}
}, 1000);
}
}
It looks like some methods currently aren't supported on iOS. These will throw IOExceptions if they are called on iOS. This is a limitation that is baked into the Cordova plugin that we ported. These methods literally return "Unsupported Operation" inside the plugin. I'm not sure if these are just omissions of the plugin, or if they can't be supported. The list of methods that are currently unsupported on iOS are:
isEnabled()
enable()
disable()
mtu()
requestConnectionPriority()
hasPermission()
requestPermission()
isLocationEnabled()
requestLocation()
I have marked these in the javadocs for the Bluetooth class to help identify them. We'll likely have to do something here to clean it up ... perhaps an exception is not the best thing.
In any case, your test app is failing because you call isEnabled() and initialize() inside the same try/catch block. isEnabled throws an exception so it never gets to initialize() and your tests aren't run.
I have adapted your code into my own test case, and made that modification, and it appears to run fine.
I made a concurrency class to test out threads. since I wanted to find out the best way to run threads at the same time.
I am surprised by my results:
test
test
Othertest
test
Othertest
test
test
test
The results I expected were for the threads to come back randomly yet they seem to come back consistently in the same order! Does anyone know why? Does this mean that they are not running concurrently? How might I go about getting them to run at the same time?
Here is my code:
public class ThreadTest {
public static void main(String args[]) throws InterruptedException
{
new Thread(new ThreadTest().test()).start();
new Thread(new ThreadTest().test()).start();
new Thread(new ThreadTest().otherTest()).start();
new Thread(new ThreadTest().test()).start();
new Thread(new ThreadTest().otherTest()).start();
new Thread(new ThreadTest().test()).start();
new Thread(new ThreadTest().test()).start();
new Thread(new ThreadTest().test()).start();
}
public Runnable test() throws InterruptedException{
Thread.sleep((long) (Math.random()*1000));
System.out.println("test");
return null;
}
public Runnable otherTest() throws InterruptedException{
Thread.sleep((long) (Math.random()*1000));
System.out.println("Othertest");
return null;
}
}
The Thread constructor accepts a Runnable on which the Thread will eventually execute the run() method. Right now you aren't returning a Runnable object. you are returning null. So the execution you do in your test() and otherTest() methods is executed synchronously.
All your execution happens in one thread. This
new Thread(new ThreadTest().test()).start();
executes test(), sleeps for a second, prints "test" and returns null. The start() call doesn't do anything because the Runnable is null. This continues for each other call you do.
You need to put everything in your test() and otherTest() methods inside a Runnable#run() method. For example
new Thread(new Runnable() {
public void run() {
Thread.sleep((long) (Math.random()*1000));
System.out.println("test");
}
}).start();
Consider the source code of the run() method of Thread class, which is executed when start() is called
#Override
public void run() {
if (target != null) {
target.run();
}
}
Where target is the Runnable reference you pass in the constructor. Obviously, if it is null, it won't do anything.
I think you might have better luck with this:
public class ThreadTest {
public static void main(String args[]) throws InterruptedException
{
new Thread(test).start();
new Thread(test).start();
new Thread(otherTest).start();
new Thread(test).start();
new Thread(otherTest).start();
new Thread(test).start();
new Thread(test).start();
new Thread(test).start();
}
public static Runnable test = new Runnable() {
#Override
public void run() {
try {
Thread.sleep((long) (Math.random()*1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test");
}
};
public static Runnable otherTest = new Runnable() {
#Override
public void run(){
try {
Thread.sleep((long) (Math.random()*1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Othertest");
}
};
}
The idea is to pass an instance of Runnable as an argument to the Thread constructor. You are not really doing that, because test() and otherTest() are both returning null. The above code shows one way of running the threads in the way that I'm guessing you want. Other approaches are certainly possible.
You need to implement your test and otherTest methods as Runnable implementations. Like so:
private static class Test implements Runnable {
#Override
public void run() {
try {
Thread.sleep((long) (Math.random()*1000));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
System.out.println("test");
}
}
private static class OtherTest implements Runnable {
#Override
public void run() {
try {
Thread.sleep((long) (Math.random()*1000));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
System.out.println("Othertest");
}
}
public static void main(String args[]) {
new Thread(new Test()).start();
new Thread(new Test()).start();
new Thread(new OtherTest()).start();
new Thread(new Test()).start();
new Thread(new OtherTest()).start();
new Thread(new Test()).start();
new Thread(new Test()).start();
new Thread(new Test()).start();
}
You could, of course, try to reduce the duplication a little:
private enum Runnables implements Runnable {
TEST {
#Override
public void run() {
if (!sleep()) return;
System.out.println("test");
}
},
OTHER_TEST {
#Override
public void run() {
if (!sleep()) return;
System.out.println("Othertest");
}
};
static boolean sleep() {
try {
Thread.sleep((long) (Math.random()*1000));
return true;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
public static void main(String args[]) {
new Thread(Runnables.TEST).start();
new Thread(Runnables.TEST).start();
new Thread(Runnables.OTHER_TEST).start();
new Thread(Runnables.TEST).start();
new Thread(Runnables.OTHER_TEST).start();
new Thread(Runnables.TEST).start();
new Thread(Runnables.TEST).start();
new Thread(Runnables.TEST).start();
}
Your Thread implementation is WRONG.
You should either implement Runnable and implement run() method or
you should extend Thread class and override run() method.
What is happening is that your test() method or otherTest() is being called just as any method calls. And since you don't have any run() method your Thread.start() wont simply run anything.
Try changing your method like below.
public Runnable test() {
return new Runnable() {
#Override
public void run() {
try {
Thread.sleep((long) (Math.random() * 1000));
System.out.println("test");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
public Runnable otherTest() {
System.out.println("Othertest");
return new Runnable() {
#Override
public void run() {
try {
Thread.sleep((long) (Math.random() * 1000));
System.out.println("Othertest");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
I am trying to learn about thread and find some examples in the internet. This is a java class that output "hello, world" every 3 seconds. But I have a feeling that the part about creating a Runable object is redundant.
Instead of writing
Runnable r = new Runnable(){ public void run(){...some actions...}};
Can I put the method run() somewhere else for easy reading?
This is what I have:
public class TickTock extends Thread {
public static void main (String[] arg){
Runnable r = new Runnable(){
public void run(){
try{
while (true) {
Thread.sleep(3000);
System.out.println("Hello, world!");
}
} catch (InterruptedException iex) {
System.err.println("Message printer interrupted");
}
}
};
Thread thr = new Thread(r);
thr.start();
}
And this is what I want to accomplish
public static void main (String[] arg){
Runnable r = new Runnable() //so no run() method here,
//but where should I put run()
Thread thr = new Thread(r);
thr.start();
}
Can I put the method run() somewhere else for easy reading?
Yes you could create your own runnable like this
public class CustomRunnable implements Runnable{
// put run here
}
and then
Runnable r = new CustomRunnable () ;
Thread thr = new Thread(r);
From the Java threads tutorial, you can use a slightly different style:
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Just make your anonymous Runnable class an inner static class, like so:
public class TickTock {
public static void main (String[] arg){
Thread thr = new Thread(new MyRunnable());
thr.start();
}
private static class MyRunnable implements Runnable {
public void run(){
try{
while (true) {
Thread.sleep(3000);
System.out.println("Hello, world!");
}
} catch (InterruptedException iex) {
System.err.println("Message printer interrupted");
}
}
}
}
Or since TickTock already extends Thread in your example code, you can just override its run method:
public class TickTock extends Thread {
public static void main (String[] arg){
Thread thr = new TickTock();
thr.start();
}
#Override
public void run(){
try{
while (true) {
Thread.sleep(3000);
System.out.println("Hello, world!");
}
} catch (InterruptedException iex) {
System.err.println("Message printer interrupted");
}
}
}