Can anyone give me the working example of reading two files simultaneously through threads? and also what would be the best way to read them at one time.
public static void main(String args[]) {
new Runnable(new File("D:/test1.log"),"thread1");
new Runnable(new File("D:/test2.log"),"thread2");
}
private static class Runnable implements Runnable {
private File logFilePath;
Thread runner;
// you should inject the file path of the log file to watch
public Runnable(File logFilePath,String threadName) {
this.logFilePath = logFilePath;
runner = new Thread(this, threadName);
runner.start();
}
_____READ LOGIC HERE____
}
Program that generates logs.I am not using any close or flush .
public final class Slf4jSample {
static Logger logger = LoggerFactory.getLogger(Slf4jSample.class);
static int i=0;
public static void main(final String[] args) {
int delay = 0; // delay for 5 sec.
int period = 10000; // repeat every sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
// Task here ...
logger.error("error"+i);
logger.warn("warn"+i);
logger.debug("debug"+i);
try{int i=0/0;
}catch(Exception e){
logger.error("Ecxeption"+i, e);
}
i++;
}
}, delay, period);
}
}
I'm not quite sure what your aim is from the short description, but I just want to warn you that reading files in parallel from a single hard disk is generally not a good idea, because the mechanical disk head needs to seek the next reading location and so reading with multiple threads will cause it to keep bouncing around and slow things down instead of speeding them up.
In case you want to read portions of files and process them in paralle, I recommend you to look at a single producer (to read the files sequentially) multiple consumer (to process the files) solution.
Edit: If you insist on using multiple readers, you should probably change your code like this:
public static void main(String args[]) {
new Thread(new ThreadTask(new File("D:/test1.log")),"thread1").start();
new Thread(new ThreadTask(new File("D:/test2.log")),"thread2").start();
}
private static class ThreadTask implements Runnable {
private File logFilePath;
// you should inject the file path of the log file to watch
public ThreadTask(File logFilePath) {
this.logFilePath = logFilePath;
}
public void run() {
// read file
}
}
You have to instantiate a thread object like Thread t = new Thread(new Runnable(.....))
and pass runnable object in Thread's constructor.
Then calling start method on thread object will start separate thread and calls Runnable's run method.
You shouldn't be creating new threads inside Runnable's constructor.
Related
How can I start a separate thread which runs my project's main class from within a Junit test?
I have a main class that instantiates Servidor() which ends up listening for socket connections, and works fine.
Here's Main:
public class Main {
public static void main(String[] args){
try{
Servidor servidor = new Servidor();
servidor.start();
}catch(Exception ex){
MyUtils.handle(ex);
}
}
}
Here's Servidor():
public class Servidor extends javax.swing.JPanel {
private static final int PUERTO = 2020;
private boolean running = false;
void start() throws Exception{
try ( ServerSocket servidor = new ServerSocket(PUERTO) ){
running = true;
String info = String.format("Listening#%s:%s",InetAddress.getLocalHost().getHostAddress(),PUERTO);
System.out.println(info);
while (running)
new ReceptorPedidosReplicacion(servidor.accept());
System.out.println("Server Stopped");
}
}
void stop(){
running = false;
}
}
However, I designed the following Junit test and as expected, it works fine as long as I have my project running in the background:
public class ServidorTest {
#Test
public void testSendPedido() throws Exception{
MySerializableObject pedido = new MySerializableObject();
Socket cliente = new Socket("127.0.0.1", 2020);
ObjectOutputStream out = new ObjectOutputStream(cliente.getOutputStream());
out.writeObject(pedido);
}
}
So what I would like to do is to be able to do something like:
#Test
public void testSendPedido() throws Exception{
Main.main(); //Option1
new Servidor().start(); //Option 2
MySerializableObject pedido = new MySerializableObject();
Socket cliente = new Socket("127.0.0.1", 2020);
ObjectOutputStream out = new ObjectOutputStream(cliente.getOutputStream());
out.writeObject(pedido);
}
However neither option works because Servidor() hijacks the execution thread and the test never gets past those lines.
Got around to it by making Servidor() implement Runnable and starting a different thread from the Junit. However, I'm not sure if Junit will handle such new threads safely. I'm guessing I'll be fine as long Servidor has no critical state changes. However I'm open to a better solution.
public class Servidor extends javax.swing.JPanel implements Runnable{
...
public void run(){start()}
}
So the test looks like this
#Test
public void testSendPedido() throws Exception{
Thread thread = new Thread(new Servidor());
thread.start();
...
}
In order to spawn a thread you can use the following:
final ExecutorService exService = Executors.newSingleThreadExecutor();
exService.execute(new Runnable() { // or use submit to get a Future (a result of computation, you'll need a Callable, rather than runnable then)
public void run() {
// do your arbitrary stuff
}
});
// do stuff in the main thread.
// waits for termination for 30 seconds
exService.awaitTermination(30, TimeUnit.SECONDS);
exService.shutdownNow();
With this construction you don't have to change your code, just place whatever you need in the run method and you're good to go. Note, of course it can work with lambdas like any java 8+ code, I've intentionally used the Java 7 style to show you which interfaces exactly are involved here.
I want to spawn a Java thread from my main java program and that thread should execute separately without interfering with the main program. Here is how it should be:
Main program initiated by the user
Does some business work and should create a new thread that could handle the background process
As soon as the thread is created, the main program shouldn't wait till the spawned thread completes. In fact it should be seamless..
One straight-forward way is to manually spawn the thread yourself:
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
runYourBackgroundTaskHere();
}
};
new Thread(r).start();
//this line will execute immediately, not waiting for your task to complete
}
Alternatively, if you need to spawn more than one thread or need to do it repeatedly, you can use the higher level concurrent API and an executor service:
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
runYourBackgroundTaskHere();
}
};
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(r);
// this line will execute immediately, not waiting for your task to complete
executor.shutDown(); // tell executor no more work is coming
// this line will also execute without waiting for the task to finish
}
Even Simpler, using Lambda! (Java 8) Yes, this really does work and I'm surprised no one has mentioned it.
new Thread(() -> {
//run background code here
}).start();
This is another way of creating a thread using an anonymous inner class.
public class AnonThread {
public static void main(String[] args) {
System.out.println("Main thread");
new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Inner Thread");
}
}).start();
}
}
And if you like to do it the Java 8 way, you can do it as simple as this:
public class Java8Thread {
public static void main(String[] args) {
System.out.println("Main thread");
new Thread(this::myBackgroundTask).start();
}
private void myBackgroundTask() {
System.out.println("Inner Thread");
}
}
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 am new to Eclipse and Java and I have researched this a fair amount, but most answers and examples (SO included) assume you have a basic understanding of where you are heading, so please explain simply (I am sure it must be simple).
I have a function such as this, which runs successfully in eclipse. However I need to be able to call this function twice and for them to run simultaneously, opposed to one after the other.
public static void reporting(String category, String message) {
// Code for this function
}
public static void main(String[] args) {
// Call the function once
reporting("one","Starting");
// Call the function a second time
reporting("two","Starting");
}
So currently instance 1 is running, then the second instance executes after the first completes. I need the first to start executing and then for the second to start straight away after. My only vague idea to this so far is this:
public static void main(String[] args) {
// Call the function once
async reporting("one","Starting");
// Call the function a second time
async reporting("two","Starting");
}
However this just throws errors about async not being a variable so clearly it isn't right.
As far as I can gather this is possible using async somehow - but as I say everywhere I look (SO
answers included) assume you have an idea of where this should fit.
(Ps, I am fully away that I maybe to totally wrong about async or there maybe a more efficient way altogether, but anything to help me learn in the right direction is beneficial)
You should extend Thread or implement Runnable for that.
You then execute the code in run methods, and start the Runnables by invoking their start methods.
Self-contained, quick and dirty example (within a Main class):
public static void main(String[] args) throws Exception {
// these are spawned as new threads,
// therefore there is no guarantee the first one runs before the second one
// (although in this specific case it's likely the first one terminates first)
new Reporter("one","Starting").start();
new Reporter("two","Starting").start();
}
static class Reporter extends Thread {
String category, message;
Reporter(String category, String message) {
this.category = category;
this.message = message;
}
#Override
public void run() {
reporting(category, message);
}
void reporting(String category, String message) {
System.out.printf("Category: %s, Message: %s%n", category, message);
}
}
You should read some Thread tutorials.
One of the many possibilities:
public static void main(String[] args)
{
try{
Thread t1 = new Thread()
{
public void run() {
reporting("one","Starting");
};
};
Thread t2 = new Thread()
{
public void run() {
reporting("two","Starting");
};
};
t1.start();//start the threads
t2.start();
t1.join();//wait for the threads to terminate
t2.join();
}catch(Exception e)
{
e.printStackTrace();
}
}
You can do create two Thread objects inside your main() like this:
Thread thread1 = new Thread () {
public void run () {
reporting("one","Starting");
}
};
Thread thread2 = new Thread () {
public void run () {
reporting("two","Starting");
}
};
Then start the 2 threads like:
thread1.start();
thread2.start();
Read more about the Thread Class and also check out some useful examples.
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.