I have a requirement in which I have to check whether any file exists in the folder. If yes, then I need to process it one by one. With my basic knowledge I have arrived to a code structure which I have posted below.
I'm creating an infinite loop and checking whether the file exists in that folder. If yes, then I'm creating a thread and processing it, else it waits for a min and checks again.
class sample {
synchronized int getNoOfFiles() {
// get number of files in the folder
}
synchronized void openFile() {
// open one file
}
synchronized void getFileContents() {
// get the file content
}
synchronized void processFileContent() {
//performing some operation on file contents
}
synchronized void closeFile() {
//closing the file
}
synchronized void deleteFile() {
//delete the file
}
}
class Test {
public static void main(String args[]) {
int flag=0;
Sample obj = new Sample();
while(1) {
flag = obj.getNoOfFiles();
if(flag) {
for(i=0;i<flag;i++) {
MyThread1 t1 = new MyThread1() {
public void run() {
obj.openFile();
obj.getFileContents();
obj.processFileContent();
obj.closeFile();
obj.deleteFile();
}
};
t1.start();
}
}
else {
try {
Thread.sleep(60000);
}
}
}
}
}
Instead of doing this kind of thing yourself, I suggest you take a look at the Timer class, that can be used to do recurring tasks. Because messing around with threads manually can often result in weird bugs.
Even better would be ScheduledThreadPoolExecutor, but it might be a bit complicated if you've never used executors before. See Keppil's answer for how to do this.
The differences between the two are nicely summed up here: Java Timer vs ExecutorService?.
I would suggest using a ScheduledExecutorService:
ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1);
executor.scheduleAtFixedRate(new Runnable() {
public void run()
{
obj.openFile();
obj.getFileContents();
obj.processFileContent();
obj.closeFile();
obj.deleteFile();
}
}, 0, 1, TimeUnit.MINUTES);
Related
I am getting StackOverflowError exception report while calling this recursive method :
private void downloadFiles(int index) {
if (index < totalFiles) {
downloadSingleFile(index, new DownloadCallback() {
#Override
public void onSuccess(String filePath) {
downloadFiles(index + 1);
}
});
}
}
I want to ask if I use a Runnable like this way:
int index = 0;
handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
downloadFiles();
}
};
handler.post(runnable);
private void downloadFiles() {
if (index < totalFiles) {
downloadSingleFile(index, new DownloadCallback() {
#Override
public void onSuccess(String filePath) {
index ++;
handler.post(runnable);
}
});
}
}
Will this be a recursivity as well and throw exception ?
Thanks
Your current use of recursion sort of defeats the purpose of using multiple threads. Currently, you only create a single thread which will enter downloadFiles(), and will then recursively try to download every file available. This is not really multithreading, it's single threading with recursion. There are several drawbacks to this approach. First, you are not taking advantage of the ability for multiple threads to do work in parallel. Second, since each subsequent recursive call is dependent on the previous one having succeeded, you are trying to download files in serial. If a given file download were to fail, it would break the rest of the recursive chain.
A better approach would be to spawn a new thread for each file download. This would allow you to use the power of multithreading to split the task in parallel, and it also allows progress to continue even if one thread were to encounter some problems.
Have a look at the following code snippet for an idea on how to approach your problem:
public class FileDownloader implements Runnable {
private index;
public FileDownloader(int index) {
this.index = index;
}
public void run() {
downloadSingleFile(index, new DownloadCallback() {
#Override
public void onSuccess(String filePath) {
// this may no longer be needed
}
});
}
}
// use a thread pool of size 5 to handle your file downloads
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int index=0; index < totalFiles; ++index) {
Runnable r = new FileDownloader(index);
executor.execute(r);
}
// shut down the thread pool executor and wait for it to terminate
executor.shutdown();
while (!executor.isTerminated()) {
}
I have a class with a method that blocks and would like to validate that it is blocking. The method is as shown below.
public static void main(String[] args) {
// the main routine is only here so I can also run the app from the command line
applicationLauncherInstance.initialize();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
if (null != application) {
applicationLauncherInstance.terminate();
}
}
});
try {
_latch.await();
} catch (InterruptedException e) {
log.warn(" main : ", e);
}
System.exit(0);
}
How can I write a unit test for such a method. I am stuck before starting.
public class ApplicationLauncherTest extends TestCase {
public void testMain() throws Exception {
ApplicationLauncher launcher = new ApplicationLauncher();
}
}
Thanks to Kulu, I found the solution.
public void testMain() throws Exception {
Thread mainRunner = new Thread(() -> {
ApplicationLauncher.main(new String[]{});
});
mainRunner.start();
Thread.sleep(5000);
assertEquals(Thread.State.WAITING, mainRunner.getState());
mainRunner.interrupt();
}
Bwire's answer is a good way there, but I highly recommend that no
one ever use Thread.sleep() in unit tests for validation of some situation. It's impossible to get the timing right:
If it's too short, you'll get a lotta false results (random failures, yay)
If it's too long, you end up creating painfully slow tests over time. Don't underestimate this.
So, what's the answer? Any time you need to "sleep" to test something, instead "wait" for that to be true (constantly checking). This way:
As soon as the condition is true, your program resumes--no wasted time.
You can set the timeout on this "wait" to a crazy large value, to avoid random failures.
Here's a modified version of Bware's self-response...
public void testMain() throws Exception {
Thread mainRunner = new Thread(() -> {
ApplicationLauncher.main(new String[]{});
});
mainRunner.start();
expectToBlock(mainRunner, 30, TimeUnit.SECONDS);
mainRunner.interrupt();
}
private static void expectToBlock(Thread thread, long waitCount, TimeUnit waitUnits) {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < waitUnits.toMillis(waitCount)) {
if (thread.getState() == Thread.State.WAITING) {
return;
}
Thread.sleep(50); // Don't hog the CPU
}
Assert.fail("Timed out while waiting for thread to block");
}
I have a static function like:
public static void foo()
{
//code follows
System.out.println(Thread.currentThread().getName());
//code follows
}
and multiple threads are calling this function concurrently. I have set the names of threads using
Thread.setName(String)
When i execute the code, the print statement will print the name of only one thread. How can i identify the names of all the threads currently executing the foo() function?
EDIT:
public class FooThread extends Thread
{
public FooThread(String name)
{
this.setName(name);
}
#Override public void run()
{
//do something
//do something
Main.foo();
}
}
//Main Class
public class Main
{
public static void main(String[] args)
{
for(int i=0;i<6;++i)
{
new FooThread("Thread"+i).start();
}
}
public static void foo()
{
//do something
while(true)
{
//do something
System.out.println(Thread.currentThread().getName());
}
}
}
You're already showing the name of the Thread that is calling your code. Code that proves this:
public class Foo2 {
public static synchronized void foo() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
int maxCount = 10;
for (int i = 0; i < maxCount; i++) {
Thread thread = new Thread(new Runnable() {
public void run() {
foo();
}
});
thread.setName("Thread " + i);
thread.start();
long sleepTime = 1000;;
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
}
}
Return:
Thread 0
Thread 1
Thread 2
Thread 3
Thread 4
Thread 5
Thread 6
Thread 7
Thread 8
Thread 9
Your problem lies in code not shown.
Either your method is being called by one and only one thread, or
Or you're giving all your threads the same name.
Again, for a complete solution as to what is actually wrong with your current set up, create and post an sscce similar to what I've posted above. For all we know you could be calling run() on your Threads, and until we can see and reproduce your problem, I don't think that we'll be able to fully understand it.
EDIT
Regarding your SSCCE: Compare the results of the two methods below, foo1() and foo2()
class FooThread extends Thread {
public FooThread(String name) {
this.setName(name);
}
#Override
public void run() {
// do something
// do something
Main.foo1(); // !! Swap comments
// Main.foo2(); // !! Swap comments
}
}
// Main Class
public class Main {
private static final long SLEEP_TIME = 4;
public static void main(String[] args) {
for (int i = 0; i < 6; ++i) {
new FooThread("Thread" + i).start();
}
}
public static void foo1() {
// do something
while (true) {
// do something
synchronized (Main.class) {
System.out.println(Thread.currentThread().getName());
}
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {}
}
}
public static void foo2() {
while (true) {
System.out.println(Thread.currentThread().getName());
}
}
}
If your while loop isn't so tight, but yields the CPU with say a short Thread.sleep, you'll see more of the different threads sharing foo in closer proximity.
But again, your code also proves that your Thread names *are8 being displayed, but that you're only seeing one name likely because that thread is hogging the CPU.
Another option is to get all the Thread stacks and look for all the threads in the foo() This has the benefit of no overhead or extra code, except to capture the information you want.
BTW: Can you make it clearer why do you need this information as I suspect there is a better way to do what you really want?
If you only want to get the count of threads, use a thread-safe counter to store number of threads. Increase the counter when foo() begins, and decrease the counter when foo() exits.
If you need to get the names, use a hash set (or list if there are duplicates of thread names) to store the names: Add the name when foo() begins, and remove the name when foo() exits. Make sure the access to hash set is thread safe. You also need another method to print out the content of the hash set, so you can call it any time to see what are the name of threads executing foo().
You can put the name into a list when the method starts (in a synchronized block) and remove it at the end again.
List allTheNames = Collections.synchronizedList(new ArrayList<String>());
public void foo() {
allTheNames.add(Thread.currentThread().getName());
// now allTheNames contains all the names of all threads currently in this method.
System.out.println(allTheNames.toString());
allTheNames.remove(Thread.currentThread().getName());
}
Of course, if you change the name of the thread in the meantime that wont work, but why would you do so?
You could also store the Thread itself if you need other informations that the name.
I need to perform 2 tasks independently.
First Task
Once per minute it should check whether there is any file in a specific folder. If there is, it should add the names of the files to a queue.
This can be done as follows:
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class schedulerExample extends Thread{
public void checkFile()
{
System.out.println("checking whether file exist in folder");
}
public void getFiles()
{
System.out.println("getting the file names");
}
public void enqueueFiles()
{
System.out.println("add files to queue");
}
public static void main(String[] args) {
final schedulerExample obj = new schedulerExample();
ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1);
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
obj.checkFile();
obj.getFiles();
obj.enqueueFiles();
}
}, 0, 1, TimeUnit.MINUTES);
}
}
Second Task
If the queue is empty , sleep for one minute or else process the file from the queue one-by-one.
public class processModel extends Thread{
public static void getQueueSize(int size)
{
System.out.println("getting queue size");
}
public void dequeue()
{
// dequeue the queue
System.out.println("dequeue");
}
public void processFile()
{
// process the file
System.out.println("process file");
}
public static void main(String[] args) {
final boolean flag = true;
final int size = 9;
final processModel obj = new processModel();
Thread t1 = new Thread(){
public void run()
{
while(flag)
{
obj.dequeue();
obj.processFile();
getQueueSize(size);
if(size == 0)
{
try
{
Thread.sleep(60000);
}
catch(InterruptedException e)
{
}
}
}
}
};
t1.start();
}
}
Now I need to do both in a single class concurrently. Is that possible?
One thread should be fetching the files once per minute. Another thread should execute files one-by-one.. if no files are there it waits for a minute and checks again. In the second method I have used an infinite loop -- instead of that, is there a way that I can perform things one-by-one?
You might want to consider using Callables with the java ExecutorService. This can be used to easily break up tasks and allow them to run concurrently. Beyond that, you can get a Future which will allow you to check the results at any time (or postpone if it's not done).
There is a great book about java and concurrency called "Concurrency in Practice."
Beyond that, Java 7 has new functionality to allow file listeners on directories. That might allow you to abstract this "check and loop" functionality.
Synchronize on the queue object when you get file from it and when you add file to it.
In the thread that reads, call wait() if the queue is empty.
In the thread that checks for new files, call notify() after you added the new file to the queue.
This is how it's usually done.
You should also prevent adding file that is being processed to the queue.
I have written a program to understand wait() and notify() methods. But when I run the program it hangs and nothing happens. Basically I want one thread (ThreadDemo) to complete its execution (display its output) thereafter other thread should display its output (ThreadDemo2).
As wait and notify requires the use of same object I have created common class LogicClass.
Can you please point out what is the problem in my code? I have to use these concepts in my project.
Program Link
In the code, I noted at least two problems:
Your main function does not wait for the child threads to join and so will exit. Use Thread::join.
You never call show() function that includes the notifyAll.
Pretty sure that non-daemon threads will not exit when the main thread exits.
I'd recommend using java.util.concurrent package if at all possible. It makes multithreading less error prone. You are missing for example a missed notification guard that can cause eternal waiting. If you were to use a latch it would solve that problem.
** EDIT
Sorry I should say your existing missed notification guard (value in LogicClass) can have cases where it doesn't function correctly - the while loops before the wait or notify aren't sufficient to guarantee which thread "wins the race" to the monitor.
I made a comment earlier about making the code shorter while still demonstrating the same behaviour. You can see one thread is running show, the other display
class ThreadMain {
public static void main(String[] args) {
final LogicClass lg = new LogicClass(true);
new Thread(new Runnable() {
public void run() {
System.out.println("In threadDemo run method");
lg.show(10);
}
}).start();
new Thread(new Runnable() {
public void run() {
System.out.println("In thread2 run method");
lg.display(5);
}
}).start();
System.out.println("Hi, in main");
}
}
class LogicClass {
boolean value;
public LogicClass(boolean value) {
this.value = value;
}
synchronized void show(int a) {
if (value) {
for (; a != 0; a--)
System.out.println("This Output should come first");
value = false;
notifyAll();
}
}
synchronized void display(int a) {
while (value) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (; a != 0; a--)
System.out.println("This should come later");
}
}