I have checked different questions in this and in other forums, but I didn't find the solution to my problem.
I have an application which runs ffmpeg and exiftool processes. I have concurrency probles, and I would like to control them, using Thread. This is how I built it:
ExiftoolThread
public class ExiftoolThread extends Thread{
String file;
public ExiftoolThread(String file){
this.file = file;
}
public void run(){
serviceToExiftool(file);//Create metadata file
}
}
FfmpegThread
public class FfmpegThread extends Thread{
String itemName;
public FfmpegThread(String itemName){
this.itemName = itemName;
}
public void run(){
serviceFFmpeg(itemName);//Create thumbnai froma video
}
}
Main call
Thread exiftoolThread = new ExiftoolThread(file.getName());
exiftoolThread.run();
try {
exiftoolThread.join(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log.write("JSON file created.It contains the metadata. ");
Thread ffmpegThread = new FfmpegThread(itemName);
ffmpegThread.run();
try {
ffmpegThread.join(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log.write("Thumbnail created successfully. ");
After this call finishes, there are more actions working with the results of these processes, and there is always one of them which is missed. I guess that's because one of them (exiftool or ffmpeg) finishes earlier and then the process continue before the other finishes.
I am using ffmpegThread.join(3000); to skip this problem, as the documentation says, this method waits untill the thread is died. What am I missing?
Thanks in advance
You need to call Thread.start() instead of Thread.run() on your two threads. The start() method actually spins a new thread to execute code concurrently, while the run() method is a normal method that executes in the calling thread like any other.
additionally, you can improve your thread synchronization setup by replacing the join() calls by use of a java.util.concurrent.CountDownLatch. Your main code will look like this:
CountDownLatch latch = new CountDownLatch(2);
Thread ffmpegThread = new FfmpegThread(itemName, latch);
Thread exifToolThread = new ExifToolThread(itemName, latch);
ffmpegThread.start();
exifToolThread.start();
latch.await(); // With optional timeout
Your two helper threads must both call latch.countDown() when they're done.
You have to call start() to run the code in the new thread. Also, join() block the current thread, so you have to call it after you start all your thread.
Related
I've an object that's created when the class is instantiated. I create a lock i-e; wait() on that object inside a background thread, however the app still gets unresponsive. My understanding of synchronization/locking is that if object.wait() is called in the main thread than it's equivalent to blocking the main thread however if it's called inside a background thread (even though the object upon which wait() is called in the main thread, shouldn't cause problems).
Can someone please help me out understanding this?
Example code:
class MyClass {
private final Object myLockObject = new Object();
public void connect() {
new Thread(new Runnable{
mSocket.connect();
myLockObject.wait(); // causing ANR
}).start();
}
private void socketConnectCallback() {
//upon callback
myLockObject.notifyAll();
}
}
class MyAndroidService extends Service {
public void onStartCommand() {
MyClass myClassObject = new MyClass();
myClassObject.connect();
//it immediately returns here even with the code written above.
}
}
First of all, this code will throw an IllegalMonitorStateException. This is because before calling object.wait(), you need to make sure that you are holding the object's monitor. One way to do this is to use:
synchronised(object) {
// this thread now owns the object's monitor
object.wait();
}
Further, the thread that calls for object.wait() relinquishes its ownership on that object's monitor and waits for some other thread to notify it. Once it gets the notification, it will wait until it reacquires the object's monitor (since some other thread might be having the ownership of that monitor even if the waiting thread got the notify signal). Then it continues normal execution.
In your case, the background thread should block, and the main thread should continue executing normally. Isn't this what you have mentioned is happening?
I don't know if this will help so much, but I can't comment so I want to get your attention to this code:
newThread(new Runnable {
mSocket.connect();
myLockObject.wait();
}).start();
This must be like:
(new Thread( new Runnable() {
public void run() {
try {
mSocket.connect(); // connect takes argument(s)
} catch (IOException e) {
// Catch the excpetion
}
try {
myLockObject.wait();
} catch (InterruptedException e) {
// Catch the excpetion
}
}
})).start();
and since Runnable is a functional interface you can use lambda expression instead of creating a new object.
Edit:
I think I figured out what do you want to do, if you want to make a thread that connects the socket and then wait to be notified and want it to acquire the intrinsic lock of the object myLockObject to prevent interleaving then you have to put the code you want to be executed by the thread in a guarded block:
private final void connectSocket() {
synchronized(myLockObject) {
try {
mSocket.connect(null);
} catch (IOException e) {
}
try {
myLockObject.wait();
} catch (InterruptedException e) {
}
}
}
and in the connect method just call connectSocket
public void connect() {
new Thread(new Runnable() {
public void run() {
connectSocket();
}
}).start();
}
I have a test that is blocking (first block of code). I have a few elements that are all working together. I have a blocking queue that I put events on to, then I have a consumer that takes them off and sends them to Amazon Kinesis. I am pretty sure that my test is getting blocked because the queue is blocking my consumer even though I thought it was running on a separate thread.
// Test.java
#Test
public void testWhileLoop() throws InterruptedException {
ArrayBlockingQueue<Event> testQ = new ArrayBlockingQueue<Event>(1024);
// mockKinesis is a mock at the class level.
KPLPoster kpl = new KPLPoster("TestStream", mockKinesis, testQ);
Event event = new Event("TestMessage", "TestPartition");
ListenableFuture<UserRecordResult> fakeReturn = Mockito.mock(ListenableFuture.class);
final AtomicInteger numberOfWhileLoops = new AtomicInteger();
Mockito.doAnswer(invocation -> {
numberOfWhileLoops.incrementAndGet();
return fakeReturn;
})
.when(mockKinesis)
.addUserRecord("TestStream", "TestPartition", ByteBuffer.wrap("TestMessage".getBytes()));
kpl.run(); // Hangs here
for(int i = 100; i > 0; i--){
testQ.put(event);
}
kpl.stop();
kpl = null;
assert(numberOfWhileLoops.toString()).equals("100");
}
Here is the run method of BaseKinesisPoster which my KPLPoster inherits. It should be noted that BaseKinesisPoster implements the Runnable interface.
//BaseKinesisPoster.java
#Override
public void run() {
shutdown = false;
while (!shutdown && !(Thread.currentThread().isInterrupted())) {
try {
this.runOnce();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}catch (Exception e){
e.printStackTrace();
}
}
}
Finally, here is part of my KPLPoster's (which extends BaseKinesisPoster) relevant runOnce() method.
// KPLPoster.java
#Override
protected void runOnce() throws Exception {
Event event = inputQueue.take();
//other stuff in my method
}
How do I make sure that blocking on my queue consumer doesn't block my test/main thread?
When you call
Thread.run();
it invokes the method called. Nothing special happens and the method is run in the current thread.
When you call
Thread.start();
This starts the thread which in turn calls run() in that new thread.
BTW Thread.stop() will throw an UnsupportedOperationException in Java 8. You shouldn't use it. You should allow it to finish naturally.
I am starting these threads:
ThreadingHDFSUsage HDFSUsage=new ThreadingHDFSUsage(dcaps);
ThreadingRAMandContainers RAMandContainers=new ThreadingRAMandContainers(dcaps);
ThreadingCoreNodesHDFSUsage CoreNodesHDFSUsage=new ThreadingCoreNodesHDFSUsage(dcaps);
ThreadingApplicationMonitoring ApplicationMonitoring= new ThreadingApplicationMonitoring(dcaps);
How should i wait for all these threads to complete before doing some other operation.
My sample thread class code for one thread operation is:
public class ThreadingHDFSUsage extends Thread {
//private PhantomJSDriver driver;
private DesiredCapabilities dcaps;
public ThreadingHDFSUsage(DesiredCapabilities dcaps) {
// TODO Auto-generated constructor stub
this.dcaps = dcaps;
}
public void run(){
System.out.println("task HDFS Usage");
PhantomJSDriver driver = new PhantomJSDriver(dcaps);
try {
Thread.sleep(10000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println(".........HDFS Usage..........");
String OverallHDFSUsage[] = null;
try {
OverallHDFSUsage = HDFSUsage.getWebData(driver,"http://1.2.3.4:8888/dfshealth.html#tab-overview","//*[#id=\"tab-overview\"]/table[2]/tbody/tr[2]/td","");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String OverallHDFSUsage1 = OverallHDFSUsage[0];
}
}
Similarly, I have relevant code for other threads.
So, how do i wait for all these 4 thread operation to complete?
Just join() them again:
HDFSUsage.join();
RAMandContainers.join();
CoreNodesHDFSUsage.join();
ApplicationMonitoring.join();
Each join() waits for the specific thread to finish.
There's also CompletionService in JDK concurrent package. To use it, you switch from explicit Threads to tasks, represented as instances of Callable<ResultType> or Runnable. While code may look slightly more complicated, it is quite convenient, once you became used to it:
import java.util.concurrent.*;
class Test {
public static void main(String[] args) throws InterruptedException, ExecutionException {
CompletionService<String> completionService = new ExecutorCompletionService<>(Executors.newCachedThreadPool());
completionService.submit(() -> {
Thread.sleep(5000);
return "sleeped for 5000 millis";
});
completionService.submit(() -> {
Thread.sleep(1000);
return "sleeped for 1000 millis";
});
// etc
System.out.println("Completed: " + completionService.take().get());
System.out.println("Completed: " + completionService.take().get());
}
}
Both of the other answers are correct, but for completeness, there's yet another way to do what you want using a Semaphore. This method won't yield results different from any of the other answers, but may be faster if any of your threads have to do something expensive after the results you want are obtained, prior to returning. Inside each of your threads, call s.release() as soon as all pertinent work is finished. Your controller thread might look like this ...
Semaphore s = new Semaphore(0);
//start all four of your threads here and pass 's' to each
s.acquire(4);
... and your worker threads might look like this:
#Override
public void run(){
//compute results
s.release(1);
//do expensive cleanup and return
}
I am new in java Android... I am trying to create two threads (named: Clean and Progress) that will run two different methods each method get the same object mix.while Clean will run a time consuming method that is part of mix's class (mix.TimeConsumingMethod();) I want Progress thread to monitor the progress of TimeConsumingMethod() by checking class variables such as mix.length and mix.framesClean
in progress I check to see mix.length > 0 if not I want Progress to wait over here my app crashes and in log CAT i get an error of:
09-20 10:37:32.773: E/AndroidRuntime(12030): java.lang.IllegalMonitorStateException: object not locked by thread before wait()
snippet of code invoking both threads:.
mix = new MixMaxMain();
progressThread = new Thread(new Runnable() {
#Override
public void run() {
Progress (mix);
}
},"Progress Thread");
CleanThread = new Thread(new Runnable() {
#Override
public void run() {
Clean (mix);
}
},"Cleaner Thread");
Log.d("STOP", "SEnding cleanThread AND progress Thread");
CleanThread.start();
progressThread.run();
snippet of Clean running time consuming method:
long time_start = SystemClock.elapsedRealtime();
mix.Run(Daudio,mu,sigSqr,c);
long time_end = SystemClock.elapsedRealtime();
snippet of Progress:
while(mix.length==0) {try {
Log.d("Progress", "Length is Zero");
Thread.sleep(1);//fails here!!
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
Log.d("Progress", "Clean Has Started");
int totalProgressLen = (int)(mix.length+0.7*mix.length);
while(mix.done==false)
{
try {
progressThread.wait(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
progress.setProgress(mix.framsClean*256/totalProgressLen );
}
You get the IllegalMonitorStateException if the thread you're calling wait on does not own the lock on the monitor you're calling it on.
To do this, you can surround the wait() call in a synchronized block. In your case, it would be something like:
synchronized(progressThread){
progressThread.wait(50);
}
There is also a way to check for this with the holdsLock(Object obj) method, which will return true only if the current thread holds the monitor lock on the specified object.
For full details, take a look at the Java Documentation on wait() for an Object.
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....
}