I have thread with this code:
public void run() {
try {
fileProcessor = new FileProcessor();
fileProcessor.process();
} catch (RuntimeException e) {
// ...
} finally {
if (fileProcessor != null) {
fileProcessor.close();
}
}
}
method fileProcessor.process(); run some new thread too:
protected void process() {
this.writer = new Writer();
final MyClient client = new MyClient();
client.start();
}
this code sometimes thrown exception
Caused by: java.io.IOException: Stream closed
at sun.nio.cs.StreamEncoder.ensureOpen(StreamEncoder.java:26)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:99)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:116)
at java.io.OutputStreamWriter.write(OutputStreamWriter.java:203)
at java.io.Writer.write(Writer.java:140)
at java.io.Writer.append(Writer.java:210)
how I can safely close stream? Because with fileProcessor.close(); now probably I close this stream but there are still some thread which use it.
use thread.join() for all threads in fileProcessor. so that it will wait until all threads finish their task.
client.start();
client.join(); // this will make sure client thread finished before proceed to next step
Link to simple tutorial on thread.join for clear understanding
Don't start a new thread in your process() method, run the functionality synchronously instead.
Alternatively call your close() method from within your process() method.
Related
While solving the task, I've noticed a behavior I can not explain.
My task was to read from InputStream and interrupt that reading after a timeout. Even though lots of people say blocking read can not be interrupted, I've achieved that goal using CompletableFuture
public void startReader() {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> doRead(System.in));
future.get(5, TimeUnit.SECONDS);
}
private void doRead(InputStream in) {
try {
new BufferedReader(new InputStreamReader(in)).readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
But when I implement the same using Future, I can see TimeoutException been thrown into JVM, but I still can see that reading thread was not terminated and still running.
public void startReader() throws ExecutionException, InterruptedException, TimeoutException {
Future<?> future = Executors.newSingleThreadExecutor().submit(() -> doRead(System.in));
future.get(5, TimeUnit.SECONDS);
}
private void doRead(InputStream in) {
try {
new BufferedReader(new InputStreamReader(in)).readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
Why there is such a difference? I believe CompletableFuture does not make any magic
Neither of your code snippets will stop the "reading" thread when you reached the future.get(5, TimeUnit.SECONDS);. They will continue waiting for your input from System.in. If you want to stop it you should send an interrupt to that thread and hope the thread react on it. Or you can force kill the thread, obviously.
However, the CompletableFuture.runAsync() and Executors.newSingleThreadExecutor() calls use different threads, specially using different daemon flags (see What is a daemon thread in Java?). When you place a System.out.println(Thread.currentThread().isDaemon()); inside your doRead() method you will see that CompletableFuture.runAsync uses a daemon thread (so it doesn't block the JVM from terminating) where Executors.newSingleThreadExecutor() does not (and keeps the JVM alive).
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 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.
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....
}
In attempts of 100% code coverage, I came across a situation where I need to unit test block of code that catches an InterruptedException. How does one correctly unit test this? (JUnit 4 syntax please)
private final LinkedBlockingQueue<ExampleMessage> m_Queue;
public void addMessage(ExampleMessage hm) {
if( hm!=null){
try {
m_Queue.put(hm);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Right before invoking addMessage(), call Thread.currentThread().interrupt(). This will set the "interrupt" status flag on the thread.
If the interrupted status is set when the call to put() is made on a LinkedBlockingQueue, an InterruptedException will be raised, even if no waiting is required for the put (the lock is un-contended).
By the way, some efforts to reach 100% coverage are counter-productive and can actually degrade the quality of code.
Use a mocking library like Easymock and inject a mock LinkedBlockingQueue
i.e.
#Test(expected=InterruptedException.class)
public void testInterruptedException() {
LinkedBlockingQueue queue = EasyMock.createMock(LinkedBlockingQueue.class);
ExampleMessage message = new ExampleMessage();
queue.put(message);
EasyMock.expectLastCall.andThrow(new InterruptedException());
replay(queue);
someObject.setQueue(queue);
someObject.addMessage(msg);
}
As stated above just make use Thread.currentThread().interrupt() if you caught InterruptedException and isn't going to rethrow it.
As for the unit testing. Test this way: Assertions.assertThat(Thread.interrupted()).isTrue();. It both checks that the thread was interrupted and clears the interruption flag so that it won't break other test, code coverage or anything below.
Another option is to delegate dealing with InterruptedException to Guava's Uninterruptibles, so you don't need to write and test your custom code for it:
import static com.google.common.util.concurrent.Uninterruptibles.putUninterruptibly;
private final LinkedBlockingQueue<ExampleMessage> queue;
public void addMessage(ExampleMessage message) {
putUninterruptibly(queue, message);
}
One proper way could be customizing/injecting the ThreadFactory for the executorservice and from within the thread factory, you got the handle of the thread created, then you can schedule some task to interrupt the thread being interested.
Demo code part for the overwrited method "newThread" in ThreadFactory:
ThreadFactory customThreadfactory new ThreadFactory() {
public Thread newThread(Runnable runnable) {
final Thread thread = new Thread(runnable);
if (namePrefix != null) {
thread.setName(namePrefix + "-" + count.getAndIncrement());
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
scheduledExecutorService.schedule(new Callable<String>() {
public String call() throws Exception {
System.out.println("Executed!");
thread.interrupt();
return "Called!";
}
},
5,
TimeUnit.SECONDS);
return thread;
}
}
Then you can use below to construct your executorservice instance:
ExecutorService executorService = Executors.newFixedThreadPool(3,
customThreadfactory);
Then after 5 seconds, an interrupt signal will be sent to the threads in a way each thread will be interrupted once in executorservice.
The example code in the question may be testable by calling Thread.currentThread().interrupt(). However, besides the mentioned problems various methods reset the interrupted flag. An extensive list is for example here: https://stackoverflow.com/a/12339487/2952093. There may be other methods as well.
Assuming waiting implemented as follows should be tested:
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException ex) {
// Set the interrupt flag, this is best practice for library code
Thread.currentThread().interrupt();
throw new RuntimeException(ex);
}
A call to Thread.sleep itself clears the interrupted flag, so it cannot be set in advance. It can be tested using its own test thread as follows:
AtomicBoolean threadInterrupted = new AtomicBoolean(false);
Runnable toBeInterrupted = () -> {
try {
methodUnderTest();
} catch (RuntimeException unused) {
// Expected exception
threadInterrupted.set(true);
}
};
// Execute the in an operation test thread
Thread testThread = new Thread(toBeInterrupted);
testThread.start();
// When the test thread is waiting, interrupt
while (!threadInterrupted.get()) {
if (testThread.getState() == Thread.State.TIMED_WAITING) {
testThread.interrupt();
}
}
// Assert that the interrupted state is re-set after catching the exception
// Must be happening before thread is joined, as this will clear the flag
assertThat(testThread.isInterrupted(), is(true));
testThread.join();