So I tried to implement a consumer - producer pattern in android the scenario is as such:
public class CameraPreview extends SurfaceView ... {
.......
public ArrayBlockingQueue<ByteBuffer> mProcessingQueue;
public CameraPreview(){
mProcessingQueue = new ArrayBlockingQueue<ByteBuffer>(10);
HandlerThread handlerThread = new HandlerThread("Image Processing Thread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
#Override
public void run() {
new ImageProcessingThread().start();
}
});
}
public void onPreviewFrame(final byte[] data, Camera camera){
.......
if(!mProcessingQueue.offer(byteBuffer)) {
byteBuffer.clear();
Log.v("IMAGE_AVOIDED", count + "");
} else {
Log.v("IMAGE_PUSHED", count + "");
}
}
public void processImage(ByteBuffer image){
.. call to opencv jni function ..
}
public class ImageProcessingThread extends Thread{
int count = 0;
#Override
public void run() {
super.run();
while(mImageProcessingRunning){
try {
ByteBuffer image = mProcessingQueue.take();
Log.v("IMAGE_TAKEN", count++ + "");
processImage(image);
image.clear();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
However when I run this code .. it never produces the IMAGE_AVOIDED log statement .. it alternates between IMAGE_TAKEN and IMAGE_PUSHED .. one frame is pushed .. and one frame processed ..
I was hoping I'd be able to constantly place frames into mProcessingQueue and when the consumer thread was ready, to take from the queue .. this way I could drop frames if the queue was full and only place the latest frames into the queue as to get closer to real time ..
I'm sure its a synchronization problem .. maybe I'm running the same two threads in one process and therefore the scheduler is hoping back and forth through tasks ?
Any ideas / pointers ??
So it turns out that the above implementation is correct .. however I was doing some calculations in the onPreviewFrame function call .. which gave the consumer thread enough time to execute the work at hand .. Thanks all !
Related
Is it possible in java to create a thread that will always work in the background? The problem is that the application instance sometimes crashes with an OutOfMemoryException. Therefore, several instances are launched in parallel. Each instance does some work: it saves something to the database at the request of the user. And the stream, which should work constantly, will look into the database and somehow process the information from it.
Most likely, the sheduler will not work, since the thread must be running constantly and wait for a signal to start working.
First of all, I suggest you investigate and resolve the OutOfMemoryException because it better to avoid these cases. You can instanziate a thread that wait for a request, execute a request and then return to wait for another request. The implementation is like this for thread:
/** Squares integers. */
public class Squarer {
private final BlockingQueue<Integer> in;
private final BlockingQueue<SquareResult> out;
public Squarer(BlockingQueue<Integer> requests,
BlockingQueue<SquareResult> replies) {
this.in = requests;
this.out = replies;
}
public void start() {
new Thread(new Runnable() {
public void run() {
while (true) {
try {
// block until a request arrives
int x = in.take();
// compute the answer and send it back
int y = x * x;
out.put(new SquareResult(x, y));
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}).start();
}
}
And for the caller method:
public static void main(String[] args) {
BlockingQueue<Integer> requests = new LinkedBlockingQueue<>();
BlockingQueue<SquareResult> replies = new LinkedBlockingQueue<>();
Squarer squarer = new Squarer(requests, replies);
squarer.start();
try {
// make a request
requests.put(42);
// ... maybe do something concurrently ...
// read the reply
System.out.println(replies.take());
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
To more information, you can start to read the post that I found here to provide you the example.
You basically need an infinitely running thread with some control.
I found this answer to be the simplest and it does what you need.
https://stackoverflow.com/a/2854890/11226302
I have the following method, that called every time I click over a button, this results to start a new thread again and again when the button is pressed, that results to multiple initialisation of thread, however I want only one thread should get executed, how can I achieve this.
private void scheduleMessages() {
new Thread(new Runnable() {
#Override
public void run() {
//Some operations
}
}).start();
}
Note: this is a small method and I don't want to create a separate class, just to make it singleton, so a solution without singleton pattern will be appreciated.
if you cannot make instance of this to check isActive() you should make a semaphore variable - a boolean, that you set to true when you start thread and set to false when you are done.
private void scheduleMessages() {
if (!taskRunning){
new Thread(new Runnable() {
#Override
public void run() {
taskRunning = true;
//Some operations
taskRunning = false;
}
}).start();
}
}
Have that thread be a background thread - maybe initialize it when the button is pressed the first time.
Have that thread listen to a queue - and act upon messages in that queue.
Whenever the button is pressed again, put a new message into the queue.
If your need to execute every requests but on a specific number of threads, you can use a thread pool and let the executor manage the queue .
private ExecutorService services;
private final static int POOL_SIZE = 1;
public MessagesService(){
services = Executors.newFixedThreadPool(POOL_SIZE);
}
public void scheduleMessages(Runnable r){
services.submit(r);
}
If you call addCall x times, x thread will be executed at the end but will never use more than the number of thread available in the pool. Here, 1 thread.
For a system that only accept one request, you can use the same approch but check the Future returned by a single thread executor. That way, you can check the status of the service.
private ExecutorService services;
private Future<?> lastCall;
public MessagesService() {
services = Executors.newSingleThreadExecutor();
lastCall = null;
}
public synchronized void scheduleMessages(Runnable r) {
if(!isScheduled()){
lastCall = services.submit(r);
}
}
public boolean isScheduled(){
return lastCall != null && !lastCall.isDone();
}
That way, the Runnable doesn't need to update a flag, which give a reusable solution.
Here is a sample of the Runnable to test these codes :
new Runnable() {
System.out.println("Running");
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
I am sending a file over network using sockets. The file is received properly without any problem. But now I am using a JProgressBar to show percentage of file sent. My problem is that even when I update GUI in a separate thread, the progress bar is updated only when file is completely sent. I also tried adjusting the priority of main thread to Thread.MIN_PRIORITY but the problem still persisted.
The complete code is long so I am not posting it (I will post if someone asks). The short code for sending file and updating progress bar is
final double temp=(done/fileSize)*100; // percentage of file sent
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
jpb.setString("Completed : "+temp+" %");
jpb.setValue((int)temp); // this is executed only when 100%
}
catch(Exception e)
{
e.printStackTrace();
}
}
});
System.out.println(temp); // only this and
bos.write(b,0,read); // this statement is executed
Problem lies in below line:
final double temp=(done/fileSize)*100; // percentage of file sent
If done and fileSize are both not double then result of done/fileSize is 0.0.
Make them double (at least one of them) to keep the decimal part of the division.
Here is a implementation that I talked about.
It's not the best design as I did it quick and dirty but this way the file transfer code is not dependent on the UI.
public class FileTransfer implements Runnable
{
double transferPercent = 0.0;
double getTransferPercent(){ return transferPercent; }
#Override
public void run()
{
while(transferingFile)
{
// Write data
// Update transferPercent
}
}
}
public class UIClass extends TimerTask
{
private FileTransfer fileTransfer;
public void createUI()
{
TimerTask myClass = this;
JButton b = new JButton("Transfer");
b.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent e)
{
fileTransfer.start();
Timer t = new Timer();
t.scheduleAtFixedRate(myClass, 0.0, 20);
}
});
}
// Update the UI here!
#Override
public void run()
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
jpb.setValue(fileTransfer.getTransferPercent());
}
});
}
}
I'd probably design this differently. I'd make the network code independent of the UI and have it just update a variable on percentage sent.
The UI would then poll this number with a timer to update the progress bar.
But your code should work. Try adding an #Override on your run function. Maybe SwingUltities.invokeLater is calling Runnable's run function instead of your own.
This is a general Java question and not an Android one first off!
I'd like to know how to run code on the main thread, from the context of a secondary thread. For example:
new Thread(new Runnable() {
public void run() {
//work out pi to 1,000 DP (takes a while!)
//print the result on the main thread
}
}).start();
That sort of thing - I realise my example is a little poor since in Java you don't need to be in the main thread to print something out, and that Swing has an event queue also - but the generic situation where you might need to run say a Runnable on the main thread while in the context of a background thread.
EDIT: For comparison - here's how I'd do it in Objective-C:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0UL), ^{
//do background thread stuff
dispatch_async(dispatch_get_main_queue(), ^{
//update UI
});
});
Thanks in advance!
There is no universal way to just send some code to another running thread and say "Hey, you, do this." You would need to put the main thread into a state where it has a mechanism for receiving work and is waiting for work to do.
Here's a simple example of setting up the main thread to wait to receive work from other threads and run it as it arrives. Obviously you would want to add a way to actually end the program and so forth...!
public static final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
public static void main(String[] args) throws Exception {
new Thread(new Runnable(){
#Override
public void run() {
final int result;
result = 2+3;
queue.add(new Runnable(){
#Override
public void run() {
System.out.println(result);
}
});
}
}).start();
while(true) {
queue.take().run();
}
}
In case you are on Android, using a Handler should do the job?
new Handler(Looper.getMainLooper()).post(new Runnable () {
#Override
public void run () {
...
}
});
An old discussion, but if it is a matter of sending request to the main thread (an not the opposite direction) you can also do it with futures. The basic aim is to execute something in background and, when it is finished, to get the result:
public static void main(String[] args) throws InterruptedException, ExecutionException {
// create the task to execute
System.out.println("Main: Run thread");
FutureTask<Integer> task = new FutureTask<Integer>(
new Callable<Integer>() {
#Override
public Integer call() throws Exception {
// indicate the beginning of the thread
System.out.println("Thread: Start");
// decide a timeout between 1 and 5s
int timeout = 1000 + new Random().nextInt(4000);
// wait the timeout
Thread.sleep(timeout);
// indicate the end of the thread
System.out.println("Thread: Stop after " + timeout + "ms");
// return the result of the background execution
return timeout;
}
});
new Thread(task).start();
// here the thread is running in background
// during this time we do something else
System.out.println("Main: Start to work on other things...");
Thread.sleep(2000);
System.out.println("Main: I have done plenty of stuff, but now I need the result of my function!");
// wait for the thread to finish if necessary and retrieve the result.
Integer result = task.get();
// now we can go ahead and use the result
System.out.println("Main: Thread has returned " + result);
// you can also check task.isDone() before to call task.get() to know
// if it is finished and do somethings else if it is not the case.
}
If your intention is to do several stuff in background and retrieve the results, you can set some queues as said above or you can split the process in several futures (starting all at once or starting a new one when needed, even from another future). If you store each task in a map or a list, initialized in the main thread, you can check the futures that you want at anytime and get their results when they are done.
You may want to use the 'even dispatching thread' where most event driven things happen. If you are using swing then:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Your code here.
}
});
Or create a class that implements Runnable and pass it into invokeLater().
If you're using JavaFX, which I highly recommend, then you can use
Platform.runLater(new Runnable() {
#Override
public void run() {
alert(text);
}
});
from within your non-UI thread, and the runnable will executed from the UI thread on return from your thread.
A little late to the party but I think that my approach is a little bit different.
Modifying Affe's solution a little bit
public static final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
public static void main(String[] args) {
Thread myThread = new Thread(
() -> {
String name = Thread.currentThread().getName();
System.out.println("initial current thread " + name);
queue.add(() -> System.out.println(Thread.currentThread().getName()));
});
myThread.setName("background thread");
myThread.start();
try {
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
while (!queue.isEmpty()) {
try {
queue.take().run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
output
initial current thread background thread
main
I have an event handling mechanism in my Android code to dump the sensor values in a file. Right now, I'm doing it in the main UI thread and hence the UI button responsiveness is very sluggish and I would like to speed it up.
How can I use multithreading on event handling functions? I'm trying to do it like this:
Create a global variable writeNow.
When the sensor value changes, set WriteNow = true
Create a thread in the class which looks like this:
Thread thread1 = new Thread()
{
public void run()
{
if(writeNow == true)
{
try
{
fos.write(s.getBytes());
}
catch (IOException e)
{
e.printStackTrace();
}
writeNow = false;
}
}
};
Thus, whenever writeNow is true, it will write to a File and then set WriteNow to false. However, I realize this is not the right approach, because the thread will execute once and then stop executing. When I tried a simple example with a while(true) and wait(), I found that the thread is interrupted millions of times.
So how do I enclose this event handling mechanism in a single thread, for speeding up a process?
Thanks!
You can try one of the following approaches:
It looks like you're trying to keep your writer thread running all the time; what you can do is spawn the thread only when you need it. Take a look at the example in the Android documentation for handling expensive operation in the UI thread.
Here is the example from that page:
public class MyActivity extends Activity {
[ . . . ]
// Need handler for callbacks to the UI thread
final Handler mHandler = new Handler();
// Create runnable for posting
final Runnable mUpdateResults = new Runnable() {
public void run() {
updateResultsInUi();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
[ . . . ]
}
protected void startLongRunningOperation() {
// Fire off a thread to do some work that we shouldn't do directly in the UI thread
Thread t = new Thread() {
public void run() {
mResults = doSomethingExpensive();
mHandler.post(mUpdateResults);
}
};
t.start();
}
private void updateResultsInUi() {
// Back in the UI thread -- update our UI elements based on the data in mResults
[ . . . ]
}
}
Since it doesn't look like you're doing anything in the UI thread once you finish writing you don't really need to bother with a Handler. But you might want to use it to display a Toast once the file has been written to.
On the other hand, if you still want to have a thread running, you might have it sleep() and periodically wake up and check the status of writeNow.
Thread thread1 = new Thread()
{
public void run()
{
while(true)
{
if(writeNow == true)
{
try
{
fos.write(s.getBytes());
}
catch (IOException e)
{
e.printStackTrace();
}
writeNow = false;
}
try
{
Thread.sleep(100); //sleep for 100 ms
}
catch (InterruptedException e)
{
Log.d('', e.getMessage());
}
}
}
};
Note that this will quickly get complicated and you might lose the bytes you want to write if your thread is sleeping when new data comes in and when it wakes up, even newer data has been received and has overwritten the previous bytes. You'd need some sort of a queue to manage that.
I'm not sure what you were doing with the wait() but that should've also worked and is in fact, the approach for problems involving a consumer and producer. The idea is to have your thread synchronize and wait() on a shared object (like perhaps your queue of bytes); a second thread will call notify() on the shared object when there is data available to write and the writer thread will be woken up. The writer thread should then write and reloop. Take a look at this tutorial.
As for the interruption of your thread, your thread may be interrupted for a number of reasons which is why it is good practice (especially when using wait()) to ensure that the condition you checked before you called wait() is still valid because you could've been woken because of either a call to notify()/notifyAll() or because of an interruption.
Handler handler = null;
handler = new Handler();
//create another class for and make consrtuctor as u want. so that u can use that effectively.
//for example.
popupIndex = new IndexThread(handler,head, target,ltp,price,IndexNifty.this,columsView,call);
popupIndex.setColumnViewexit(columsView);
handler.postDelayed(popupIndex, 300);
//another class
public IntraThread(Handler handler,String script,int target,int ltp,int price,Intraday intraday,TextView columsView,String call){
super();
this.target = target;
this.ltp = ltp;
this.price = price;
this.intraday = intraday;
this.columsView = columsView;
this.script= script;
this.handler= handler;
this.call= call;
}
public void run(){
// write ur code here....
}