I'm trying to build an ane who take an empty bitmap
bitmapData = new BitmapData(size.width,size.height,false, 0x00000000);
acquire it, edit the bytebuffer in a different thread then release it.
Here's the call function code in the java part
public FREObject call(FREContext freContext, FREObject[] args) {
try {
FREBitmapData bitmapData = (FREBitmapData)args[0];
bitmapData.acquire();
ByteBuffer bytebuffer =
myTaskProcessingQueue.put(new Task(freContext,bitmapData,bytebuffer)); //edit the bitmap data in a specific thread
} catch (InterruptedException e) {
Log.e(TAG, "exception", e);
} catch (FREInvalidObjectException e) {
Log.e(TAG, "exception", e);
} catch (FREWrongThreadException e) {
Log.e(TAG, "exception", e);
}
return null;
}
And when I'm done with the bytebuffer :
new Handler(Looper.getMainLooper()).post(new Runnable () {
#Override
public void run () {
try {
Toast.makeText(task.context.getActivity(),"Toast",Toast.LENGTH_SHORT).show();
task.bitmapData.release();
} catch (FREInvalidObjectException e) {
Log.e("InitExtractorFunction", "FREInvalidObjectException", e);
} catch (FREWrongThreadException e) {
Log.e(TAG, "exception", e);
}
}
});
The toast instruction works fine, but the bitmapData.release() one throws a FREWrongThreadException even though I am on the main thread, and I can't find any documentation about this exception on the adobe website.
Any idea?
Edit :
Here's more code for the thread class where i'm editing the data :
private class MyTaskWorker extends Thread {
#Override
public void run() {
while (true) {
try {
processMyTask(myTaskProcessingQueue.take());
} catch (InterruptedException e) {
Log.e(TAG,"InterruptedException", e);
}
}
}
private void processMyTask(Task task) {
// do work with bytebuffer
new Handler(Looper.getMainLooper()).post(new Runnable () {
#Override
public void run () {
try {
Log.d(TAG, "Thread: " + Thread.currentThread().getName());
Toast.makeText(task.context.getActivity(),"Toast",Toast.LENGTH_SHORT).show();
task.bitmapData.release();
Log.i(TAG,"bitmap released");
} catch (FREInvalidObjectException e) {
Log.e(TAG, "FREInvalidObjectException", e);
} catch (FREWrongThreadException e) {
Log.e(TAG,"FREWrongThreadException", e);
}
}
});
}
}
Edit 2 :
I also tried to do both the acquire and the relase in the same background thread and still no dice. The only way I managed to make it work is when I do both the acquire and the release inside the call function, but I don't want to block the main thread to wait for the bitmap modification...
Just like regular multithreading, whenever you acquire a lock, it must be released by the same thread who locked it.
The documentation for this exception has the following description:
FRE_WRONG_THREAD The method was called from a thread other than the one on which the runtime has an outstanding call to a native extension function.
Thus when call() is called from a background thread, the background thread is the one that locks bitmapData, which means the main thread does not own the lock to release it later.
You can always test this by logging the thread name in each location:
Log.d(..., "Thread: " + Thread.currentThread().getName());
The solution will be to ensure that the release() method is invoked from the same place (thread) as call() (wherever this may be)
Related
I'm having an app which enables a customer to place an order for a ride (as in Uber), initially considered in a "WAITING" phase. When a driver accepts the order, it is automatically set in an "ACCEPTED" phase.
When ACCEPTED, the user is going to be redirected to another scene, telling him that he needs to wait for his rider to pick him up.
I decided to create a thread that checks every 250ms if the status of his order was set to ACCEPTED, like that:
public class AcceptanceRunnable implements Runnable {
private boolean running;
public AcceptanceRunnable() {
running = true;
}
public void run() {
do {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (OrderService.checkIfAccepted(OrderSession.getOrder())) {
// move to other scene
break;
}
} while(running);
}
public void setRunning(boolean running) {
this.running = running;
}
}
This AcceptanceRunnable class gets instantiated within the controller in the initialize() method:
#FXML
public void initialize() throws InterruptedException, IOException {
sourceAddress.setText("From: " + OrderSession.getOrder().getSourceAddress());
destinationAddress.setText("To: " + OrderSession.getOrder().getDestinationAddress());
price.setText("You'll need to pay RON " +
UserService.calculatePrice(UserSession.getUser()) + " for this ride.");
acceptanceRunnable = new AcceptanceRunnable();
Thread t = new Thread(acceptanceRunnable);
t.start();
}
Everything works fine. If I just print out some lines while waiting for the order's status to get changed, it seems to be okay. The problem is, I want my user to be redirected to another scene, if his order gets accepted.
This means, I need to insert something in place of the comment made in my AcceptanceRunnable.run() method.
I also tried changing the scene by having a method called ifAccepted() inside my controller, which actually triggers the method that changes the scene:
if (OrderService.checkIfAccepted(OrderSession.getOrder())) {
try {
Class<?> controller = Class.forName("com.example.yuber.controllers.CustomerWaitController");
Method ifAccepted = controller.getMethod("ifAccepted");
ifAccepted.invoke(controller.newInstance());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
break;
}
But I only get some NullPointerException and I'm pretty sure that what I do here isn't really correct.
Any opinions?
As Slaw suggested, using Platform#runLater(Runnable) fixed my problem.
What I actually did was add my run() method from the Runnable inside my controller, renaming it to handleTread():
public void handleThread() {
do {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (OrderService.checkIfAccepted(OrderSession.getOrder())) {
Platform.runLater(() -> {
try {
SceneService.NewScene("/com/example/yuber/accepted-view.fxml", (Stage) rootPane.getScene().getWindow(), rootPane.getScene());
} catch (IOException e) {
e.printStackTrace();
}
});
break;
}
} while(running);
}
Not using Platform.runLater(...) would result in receiving a Not on FX Application Thread error.
Everything seems to be fine now.
I'm using the ReadData class from https://github.com/iota-community/java-iota-workshop/blob/master/src/main/java/com/iota/ReadData.java to retrieve a message from the Iota Tangle (essentially a distributed Network) via a hash value (the bundlehash).
That's my method:
private String readMessageFromHash(String BundleHash) {
final String[] s = new String[]{""};
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
s[0] = ReadData.getTMessage(BundleHash);
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return s[0];
}
I need the return value in my next line of code but without multithreading my program crashes.
With mutlithreading it sometimes works, but most of time it doesn't work (returns an empty String).
I tried using:
thread.start();
try {
while(s[0].length < 1){}
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return s[0];
but it just loops infinitely.
I think the issue is my program not waiting long enough for a response from the network.
I am using a Java based file conversion tool which converts PDF to DOCX, but sometimes while conversion it stuck, if input file size is more then 1 MB and start utilizing 100% CPU and more memory and keep running. I want to stop this continuous thread.
I know stop() function is deprecated.
Calling thread.interrupt(); is not helping, since thread is keep running.
There is no loop in the code ...so cannot check for interrupted flag in loop
How to Stop a running Thread t.
public class ThreadDemo implements Runnable {
Thread t;
PdfToDocConversion objPdfToDocConversion;
ThreadDemo() throws InterruptedException {
t = new Thread(this);
System.out.println("Executing " + t.getName());
// this will call run() fucntion
t.start();
Thread.sleep(2000);
// interrupt the threads
if (!t.interrupted()) {
System.out.println("Interrupted");
t.interrupt();
}
System.out.println(t.isInterrupted()); // true
System.out.println(t.getName());
System.out.println(t.isAlive()); /// still true
// block until other threads finish
try {
t.join();
} catch (InterruptedException e) {
}
}
public void run() {
objPdfToDocConversion = new PdfToDocConversion();
try {
objPdfToDocConversion.convertDocToPdf();//inside this function thread got stuck
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.print(t.getName() + " interrupted:");
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String args[]) {
try {
new ThreadDemo();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You can build your own logic in killing the thread by the help of boolean flag.
public class RunningThread implements Thread {
private volatile boolean running = true;
public void run() {
while (running) {
try {
// Add your code here
} catch (InterruptedException e) {
if(!running){
break;
}
}
}
}
public void stopThread() {
running = false;
interrupt();
}
}
Here is the usecase:
RunningThread thread = new RunningThread();
thread.start(); // start the thread
thread.stopThread(); // stops the thread
The approach above is originally used by Google developers in on of there framework a.k.a Volley library.
Thread.interrupt() only sets a flag within the Thread object that the Thread should be interrupted. It does not cause the target Thread to throw an InterruptedException, instead code that can be interrupted must continually check that flag to see if someone has requested it be interrupted. That code then must handle it, usually by throwing an InterruptedException.
Some of the answers say about stopping the loop with volatile boolean isRunning but I do not see any loop in your example. Interrupting the thread does not actually interrupt it "right now". It just says "thread will be interrupted as soon as there will be such an opportunity". In your case I would suggest to close your PDF file and flag it with some boolean - then you can catch the IOException and if the flag is set - it means that you caused this situation and you can finish the thread.
I have a Producer-Consumer problem to implement in Java, where I want the producer thread to run for a specific amount of time e.g. 1 day, putting objects in a BlockingQueue -specifically tweets, streamed from Twitter Streaming API via Twitter4j- and the consumer thread to consume these objects from the queue and write them to file. I've used the PC logic from Read the 30Million user id's one by one from the big file, where producer is the FileTask and consumer is the CPUTask (check first answer; my approach uses the same iterations/try-catch blocks with it). Of course I adapted the implementations accordingly.
My main function is:
public static void main(String[] args) {
....
final int threadCount = 2;
// BlockingQueue with a capacity of 200
BlockingQueue<Tweet> tweets = new ArrayBlockingQueue<>(200);
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(threadCount);
Future<?> f = service.submit(new GathererTask(tweets));
try {
f.get(1,TimeUnit.MINUTES); // Give specific time to the GathererTask
} catch (InterruptedException | ExecutionException | TimeoutException e) {
f.cancel(true); // Stop the Gatherer
}
try {
service.submit(new FileTask(tweets)).get(); // Wait til FileTask completes
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
service.shutdownNow();
try {
service.awaitTermination(7, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Now, the problem is that, although it does stream the tweets and writes them to file, it never terminates and never gets to the f.cancel(true) part. What should I change for it to work properly? Also, could you explain in your answer what went wrong here with the thread logic, so I learn from my mistake? Thank you in advance.
These are the run() functions of my PC classes:
Producer:
#Override
public void run() {
StatusListener listener = new StatusListener(){
public void onStatus(Status status) {
try {
tweets.put(new Tweet(status.getText(),status.getCreatedAt(),status.getUser().getName(),status.getHashtagEntities()));
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentTread.interrupt(); // Also tried this command
}
}
public void onException(Exception ex) {
ex.printStackTrace();
}
};
twitterStream.addListener(listener);
... // More Twitter4j commands
}
Consumer:
public void run() {
Tweet tweet;
try(PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("out.csv", true)))) {
while(true) {
try {
// block if the queue is empty
tweet = tweets.take();
writeTweetToFile(tweet,out);
} catch (InterruptedException ex) {
break; // GathererTask has completed
}
}
// poll() returns null if the queue is empty
while((tweet = tweets.poll()) != null) {
writeTweetToFile(tweet,out);
}
} catch (IOException e) {
e.printStackTrace();
}
}
You should check if your Thread classes are handling the InterruptedException, if not, they will wait forever. This might help.
I wrote a thread class that checks the socket connection to the server by sending a small string every one second.
begin() method executes the thread.
After connection is lost, the thread tries to connect again.
My question is if it's ok to re-run by begin() the thread inside the run() method like I did (see below).
public void begin() {
Check = new Thread(this);
Check.start();
}
#Override
public void run() {
Thread thisThread = Thread.currentThread();
while (Check==thisThread) {
try {
oos.writeObject("a");
// oos.flush();
synchronized (this) {
while (pleaseWait) {
try {
System.out.println("waiting");
wait();
System.out.println("not waiting");
}
catch (Exception e) {
System.err.println("Thread is interrupted: "+e.getMessage());
}
}
}
sleep(1000);
} catch (Exception ex) {
v = new Visual("The connection is lost. The system will try to reconnect now.");
this.end();
try {
Server=ClientLogin.checkingServers(); //returns the reachable server string address
socket = new Socket(Server, ServerPort);
System.out.println("Connected: " + socket);
oos = new ObjectOutputStream(socket.getOutputStream());
begin();
v = new Visual("The system is reconnected.");
}
catch(UnknownHostException uhe){
System.out.println("Host unknown: " + uhe.getMessage());
v = new Visual("The system has failed to reconnected.");
}
catch (IOException ioe) {
System.out.println("The system cannot connect to servers: " + ioe.getMessage());
v = new Visual("The system has failed to reconnected.");
}
catch (Exception e) {
System.out.println("The system has failed to reconnect: " + e.getMessage());
v = new Visual("The system has failed to reconnected.");
}
}
}
}
public void end() {
Check = null;
}
I don't know any reason why that wouldn't work, but it looks kinda messy. You may have to declare Check as volatile to ensure that the loop always reads the current value, for those times when the new thread overwrites it.
IMHO a better approach would be a separate "supervisor" thread which is responsible for starting one of these threads, and then uses Thread.join() to wait for it to die, at which point it can start it up again.
In this way your main thread's logic can concentrate on exactly what it's supposed to do, without needing to have any "self awareness".
First, the code is not thread safe. The "Check" field is written by one thread but read by another, but it is not synchronised. There is no guarantee that the new started thread is going to see the updated value of "Check", i.e. the new thread will get the old thread's reference when checking "Check==thisThread" and do the wrong thing,
This particular problem can be fixed by making "Check" field volatile. It makes sure when it is updated, every thread will see the new value.
It is not "wrong" to call "begin()" in the run() method. However I wouldn't recommend it because you created a recursive call here effectively. There is a good chance you will get it wrong and fall into infinite loop. Try the simple design below. It uses a while loop instead of recursion.
package com.thinkinginobjects;
public class HeathChecker {
public void run() {
while (true) {
boolean success = checkHeath();
if (!success) {
//log and re-establish connection
} else {
Thread.sleep(1000);
}
}
}
private boolean checkHeath() {
try {
oos.writeObject("a");
return true;
} catch (Exception ex) {
return false;
}
}
}
it is ok, however why do you need to start a thread every time? Isn't it better to use Timer and TimerTask?
http://docs.oracle.com/javase/6/docs/api/java/util/TimerTask.html
http://docs.oracle.com/javase/6/docs/api/java/util/Timer.html