Implementing Wait and Notify - java

I'm trying to write a program that checks on the health of a database. One of the elements of the elements of the program is supposed to be that the program queries a database and then waits 5 minutes using wait. If there is no response it notifies and sends out some emails. My connection to the database/sending out emails all works, but i'm having trouble implementing wait and notify.
I read the api and its easy to understand in a simple program, but i'm really confused as to how to implement it in this case with all the additional complications because of errors where I can't call something dynamic from a static method.
I've been reading through lots of threads with wait and notify, but haven't figured out how do to it correctly in my program. If anyone could give me a few tips it would be a huge help. Thanks!
import com.fmr.ipgt.email.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import javax.mail.MessagingException;
class MyResource {
synchronized void qQuery() throws Exception {
String query = ".z.k"; // The query that is used to query q; this can be changed here.
int version = 0;
c qConn = null;
qConn = new c(Main.host,Main.port); // Connect to the q database
while (Main.healthy) {
Object o = qConn.k(query); // Query q
version = c.t(o);
if(!(version==0)) {
break; // End the process if the database responds
}
}
}
synchronized void start() throws Exception {
Main.setHealth(false);
Main.sendMessages();
}
}
class MyThread implements Runnable {
MyResource myResource;
MyThread(String name, MyResource so) {
myResource = so;
new Thread(this, name).start();
}
public void run() {
try {
myResource.qQuery(); // Begin a method to query q.
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Main {
private static String[] recipients;
private static String subject = "Database Failure";
private static String message = "The database has failed or is in a hung state";
private static String from;
static String host;
static int port;
private static String emails;
private static int minutes;
static boolean healthy = true;
public static void main(String args[]) throws Exception {
// Import information from the configuration file
SAXBuilder builder = new SAXBuilder();
File xmlFile = new File("/export/home/jflt/file.xml"); // Note: The directory for the configuration file may need to be changed
try {
Document document = (Document) builder.build(xmlFile);
Element rootNode = document.getRootElement();
List list = rootNode.getChildren("parameters");
Element node = (Element) list.get(0);
host = node.getChildText("host");
port = Integer.parseInt(node.getChildText("port"));
emails = node.getChildText("emails");
String delims = "[ ]+";
recipients = emails.split(delims); // parse email list
minutes = Integer.parseInt(node.getChildText("time"));
from = node.getChildText("from");
} catch (IOException io) {
System.out.println(io.getMessage());
} catch (JDOMException jdomex) {
System.out.println(jdomex.getMessage());
}
MyResource unhealthy = new MyResource();
new MyThread("MyThread", unhealthy); // Create new Thread
new MyThread("WaitThread", unhealthy);
while(healthy) {
Thread.sleep(minutes*60000); // The wrong thread is sleeping here. The main method should probably be a different thread instead which will then need to wait and the second thread will notify.
}
unhealthy.start(); // The database has not responded for the given time. Report that it is unhealthy.
}
public static void setHealth(boolean health){
System.out.println("database unhealthy");
healthy = health;
}
public static void sendMessages() throws MessagingException {
System.out.println("sending emails");
FCAPMailSender.postMail(recipients,subject,message,from);
}
}

If wait and notify is to be used, i will advice you to use the Lock Interface and Reentrant Lock Class from java.util.concurrent package...

Schedule a task with an ExecutorService that sends email. When you get a response, cancel the task. If it's been more than 5 minutes, the mail has already been sent by the executor thread, and cancellation is a no-op. Otherwise, the email is aborted.
This isn't even a wait()/notify() problem; there's no data passing between threads. Here's a low level equivalent to the ExecutorService solution.
void test() {
Thread t = new Thread() {
#Override
public void run() {
try { Thread.sleep(TimeUnit.MINUTES.toMillis(5)); }
catch(InterruptedException abort) { return; }
email();
}
}
t.start();
query();
t.interrupt();
}

Related

Two server threads in a while loop blocking each other

everybody.
Hope you can help me with this one:
I have two threads, which are tasked with handling connections from a client.
This is my code
ServerSocket loginSocket = new ServerSocket(8000);
ServerSocket fileSocket = new ServerSocket(7000);
while (running) {
new LoginThread(loginSocket.accept(),loginInormation).start();
new LoaderThread(fileSocket.accept()).start();
}
When I try to connect to the loginSocket two times, the server will block and stop working, blocking the client, but this doesn't happen if I delete this:
new LoginThread(loginSocket.accept(),loginInormation).start();
I'm not getting any error messages, so why is this happening and how can I fix this?
The accept() method is a blocking method, which means that your program won't continue until a connection is made with loginSocket().
When you're creating your LoginThread, the program waits a connection to set the first parameter of your object, and it will not continue the execution until a connection is made.
The line new LoginThread(loginSocket.accept(),loginInormation).start(); contains the method call loginSocket.accept(), which will be called before this thread is created. This method call will block until a client logs in. (In addition, the second thread will be blocked by fileSocket.accept()).
As for a solution, I would move the accept() calls to inside each of the Threads. You will need to pass the sockets to the threads for them to do this.
Start fileSocket and login socket in different threads
package com.ca.training.task.app;
import java.io.IOException;
import java.net.ServerSocket;
public class App {
public void execute() {
LoginRunnable loginRunnable = new LoginRunnable();
loginRunnable.setLoginInformation(new Object());//Login information
FileRunnable fileRunnable = new FileRunnable();//Data for loaded runnable.
fileRunnable.setParams(new Object());
startLoginThread(loginRunnable);
startFileThread(fileRunnable);
}
private static void startLoginThread(LoginRunnable loginRunnable) {
Thread loginThread = new Thread(loginRunnable);
loginThread.start();
}
private static void startFileThread(FileRunnable fileRunnable) {
Thread loadedThread = new Thread(fileRunnable);
loadedThread.start();
}
class LoginRunnable implements Runnable {
private Object loginInformation;
#Override
public void run() {
try {
ServerSocket loginSocket = new ServerSocket(8000);
loginSocket.accept();
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getLoginInformation() {
return loginInformation;
}
public void setLoginInformation(Object loginInformation) {
this.loginInformation = loginInformation;
}
}
class FileRunnable implements Runnable {
private Object params;
#Override
public void run() {
try {
ServerSocket fileSocket = new ServerSocket(7000);
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getParams() {
return params;
}
public void setParams(Object params) {
this.params = params;
}
}
}

Dispose Child Thread As per the Id

I am generating a child thread when I receive data from user.
What are the steps if I want to dispose the previous user child thread if the same user sends data again and wants to generate a new user child thread again?
Right, so java can't dispose of the thread, a thread simply runs until it terminates.
So:
To get rid of the thread you need to allow the threads run method to end and then get rid of all references to the Thread and any Runnable it's constructed with.
You want to toggle the thread finishing so, a simple example:
class SimpleRunnable implements Runnable {
public volatile boolean run = true; //Volatile for thread safety.
public void run() {
while(run) {
System.out.println("WHOOOO!"); //Boy, will this be annoying
}
}
}
Creating a thread from this runnable:
SimpleRunnable run = new SimpleRunnable();
Thread thread = new Thread(run);
Thread.start(); //run thread
//Stop thread
run.run=false;
//Thread will be removed when out of scope
Youu need to create a Runnable per user in your case, and then call set the stop variable when a new thread is created.
For example, you could store each runnable in a ConcurrentHashMap by userId.
ConcurrentHashMap<String,SimpleRunnable> runnablesByUser = new ConcurrentHashMap<>();
public void startNewThreadForUser(String userId){
//Time passes, retrieve and kill old thread:
SimpleRunnable oldRunnable = runnableByUser.get(userId);
if(oldRunnable!=null){
oldRunnable.run=false;
}
SimpleRunnable newRunnableUserOne = new SimpleRunnable();
runnablesByUser.put(userId,newRunnableUserOne);
Thread thread = new Thread(newRunnableUserOne);
thread.start();
}
Calls to the method would then kill an old thread if found, release the old one from scope by replacing it with a new one in the ConcurrentHashMap and finally start the new thread.
Like so:
public void startThreeThreads(){
startNewThreadForUser("User1");//starts Thread for User1
startNewThreadForUser("User2");//starts Thread for User2
startNewThreadForUser("User1");//Replaces Thread for User1
}
Managing running threads is typically done in a thread pool and this is rough in all sorts of ways, but hopefully it's useful.
I can elaborate that mechanism if you want.
Starting a new thread every time that you receive data from a user will lead to running out of resources, besides causing an unnecessary overhead of managing too many threads. Your computer has a limited number of threads that can run at any single time and is limited by your CPU. to find out that number you can use command
Runtime.getRuntime().availableProcessors()
on the other hand, if the jobs that you want to process require a lot of I/O processing, you should launch a few more threads than "Runtime.getRuntime().availableProcessors()", or you will be under-using your CPU.
what I would do is to use a "ExecutorService" which will handle the threads for you (no need to manually start, stop threads). Just start an "ExecutorService" with the total number of threads that you want to execute simultaneously, and then every time that you get more work from a User, submit the new task (as a Callable) to the ExecutorService. The executorService will handle the execution of that task for you, and once it is done it will become available for garbage collection.
for example, see code below:
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MultipleClientsExample {
public static final int TOTAL_THREADS_TO_PROCESS_CUSTOMER_WORK = 4;
public static final Random random = new Random();
public static int customerCounter = 0;
public static void main(String[] args) throws InterruptedException {
MultipleClientsExample multipleClientsExample = new MultipleClientsExample();
multipleClientsExample.doTheWork();
}
private void doTheWork() throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(TOTAL_THREADS_TO_PROCESS_CUSTOMER_WORK);
while (customerCounter < 10) {
try {
CustomerInput customerInput = getWorkFromCustomer();
System.out.println("main program. received work from customer: " + customerInput.getCustomerId());
executorService.submit(new WorkToBeDone(customerInput.getCustomerId(), customerInput.getWorkInfo()));
} catch (InterruptedException e) {
break;
}
customerCounter++;
}
executorService.shutdown();
executorService.awaitTermination(5, TimeUnit.SECONDS);
}
private CustomerInput getWorkFromCustomer() throws InterruptedException {
while (true) {
String customerId = String.valueOf(random.nextInt(10));
CustomerInput customerInput = new CustomerInput(customerId, "work from customer: " + customerId);
return customerInput;
}
}
}
class WorkToBeDone implements Callable<Void> {
private String clientId;
private String workInfo;
public WorkToBeDone(String clientId, String workInfo) {
this.clientId = clientId;
this.workInfo = workInfo;
}
#Override
public Void call() throws Exception {
System.out.println("inside a working thread: it is going to do the work of customer: " + clientId);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("worker processing job from customer: " + clientId + " was interrupted. ending now");
return null;
}
System.out.println("work completed for customer: " + clientId);
return null;
}
}
class CustomerInput {
private String customerId;
private String workInfo;
public CustomerInput(String customerId, String workInfo) {
this.customerId = customerId;
this.workInfo = workInfo;
}
public String getCustomerId() {
return customerId;
}
public String getWorkInfo() {
return workInfo;
}
}
In case you want the ability to cancel a task that has already been submitted to the thread pool, you will have to keep reference of the Future values of each task, and make sure to remove the reference of the tasks that completed and that you cancelled, so they are ready to be garbage collected (otherwise you will have a memory leak).
for example
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class MultipleClientsExample {
public static final int TOTAL_THREADS_TO_PROCESS_CUSTOMER_WORK = 4;
public static int customerCounter = 0;
public static void main(String[] args) throws InterruptedException {
MultipleClientsExample multipleClientsExample = new MultipleClientsExample();
multipleClientsExample.doTheWork();
}
private void doTheWork() throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(TOTAL_THREADS_TO_PROCESS_CUSTOMER_WORK);
Map<String, Future<String>> map = new ConcurrentHashMap<>();
while (customerCounter < 11) {
try {
WorkToBeDone workToBeDone = getWorkFromCustomer();
System.out.println("main program. received work from customer: " + workToBeDone.getClientId());
Future<String> resultFuture = executorService.submit(workToBeDone);
map.put(workToBeDone.getClientId(), resultFuture);
} catch (InterruptedException e) {
break;
}
customerCounter++;
}
// cancel job of customer with id: 10
Future<String> resultFuture = map.get("10");
System.out.println("cancelling job of customerId: 10");
resultFuture.cancel(true);
// remove references of all completed jobs
Thread.sleep(2000);
System.out.println("looking for jobs that completed or were cancelled.");
Iterator<Map.Entry<String, Future<String>>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Future<String>> entry = iterator.next();
if (entry.getValue().isCancelled() || entry.getValue().isDone()) {
System.out.println("removing reference of job for customer: " + entry.getKey());
iterator.remove();
}
}
// simpler way to remove entries from map (but doesn't print output of jobs removed from map)
// map.entrySet().removeIf(entry -> entry.getValue().isCancelled() || entry.getValue().isDone());
executorService.shutdown();
executorService.awaitTermination(5, TimeUnit.SECONDS);
}
private WorkToBeDone getWorkFromCustomer() throws InterruptedException {
String customerId = String.valueOf(customerCounter);
WorkToBeDone workToBeDone = new WorkToBeDone(customerId, "work from customer: " + customerId);
return workToBeDone;
}
}
class WorkToBeDone implements Callable<String> {
private String clientId;
private String workInfo;
public String getClientId() {
return clientId;
}
public WorkToBeDone(String clientId, String workInfo) {
this.clientId = clientId;
this.workInfo = workInfo;
}
#Override
public String call() throws Exception {
System.out.println("inside a working thread: it is going to do the work of customer: " + clientId);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("worker processing job from customer: " + clientId + " was interrupted. ending now");
return clientId;
}
System.out.println("work completed for customer: " + clientId);
return clientId;
}
}

Stop/Kill Runnable Thread - Start new Runnable thread - Java

Im trying trying to stop a runnable thread from a Swing GUI. When I click on the button to stop the runnable thread it stops it but I am unable to start a new runnable thread afterwards.
Does anyone know why this is? Any help would be appreciated.
Thanks
Here's my GUI Code Listnere
if(button.getText().equals("Start Scraper")){
if(validate())
{
updateThread.running = true;
button.setText("Stop Scraper");
String searchType = comboBox.getSelectedItem().toString();
String email = emailTextField.getText();
String password = passwordTextField.getText();
String searchTerm = searchTermTextField.getText();
try{
thread = new updateThread(searchTerm, searchType, email, password );
thread.start();
}catch(Exception ex){
System.out.println("Something went wrong in the GUI");
ex.printStackTrace();
}
}else{
//not valid go again
}
}else{
button.setText("Start Crawler");
updateThread.running = false;
updateThread.terminate();
}
}
});
Here's my runnable thread class
package guiTool;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.SessionNotFoundException;
import linkedIncrawler.common.Utils;
import linkedin.actions.BaseClass;
import linkedin.actions.LinkedInActions;
public class updateThread extends Thread
{
private static WebDriver driver;
public String searchTerm, searchType, email, password;;
public volatile static Boolean running = true;
public updateThread(String searchTerm2, String searchType2, String email2, String password2)
{
email = email2;
password = password2;
searchTerm = searchTerm2;
searchType = searchType2;
}
public static void terminate() {
currentThread().interrupt();
//thread.stop();
driver.quit();
running = false;
}
#Override
public void run()
{
while(running)
{
try {
driver = Utils.OpenBrowser("SearchTerms");
new BaseClass(driver);
LinkedInActions.Execute(searchTerm, searchType, email, password);
driver.quit();
} catch (Exception e) {
System.out.println("2nd thread cant run linkedin");
e.printStackTrace();
}
}
}
}
Once a thread has died, it is dead... You need to create a new one. There are important reasons as to why you can't re-start a dead thread.
Rather than extending Thread, maybe implement Runnable/Callable?
public volatile static Boolean running = true;
this variable, being common for all instances, stops all updateThread's, current and future. Remove static modifier.

Text is not getting printed once the Threads are done [duplicate]

This question already has answers here:
How to wait for all threads to finish, using ExecutorService?
(27 answers)
Closed 8 years ago.
Please have a look at the following code.
public class BigFileWholeProcessor {
private static final int NUMBER_OF_THREADS = 2;
public void processFile(String fileName) {
BlockingQueue<String> fileContent = new LinkedBlockingQueue<String>();
BigFileReader bigFileReader = new BigFileReader(fileName, fileContent);
BigFileProcessor bigFileProcessor = new BigFileProcessor(fileContent);
ExecutorService es = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
es.execute(bigFileReader);
es.execute(bigFileProcessor);
es.shutdown();
if(es.isTerminated())
{
System.out.println("Completed Work");
}
}
}
public class BigFileReader implements Runnable {
private final String fileName;
int a = 0;
public static final String SENTINEL = "SENTINEL";
private final BlockingQueue<String> linesRead;
public BigFileReader(String fileName, BlockingQueue<String> linesRead) {
this.fileName = fileName;
this.linesRead = linesRead;
}
#Override
public void run() {
try {
//since it is a sample, I avoid the manage of how many lines you have read
//and that stuff, but it should not be complicated to accomplish
BufferedReader br = new BufferedReader(new FileReader(new File("E:/Amazon HashFile/Hash.txt")));
String str = "";
while((str=br.readLine())!=null)
{
linesRead.put(str);
System.out.println(a);
a++;
}
linesRead.put(SENTINEL);
} catch (Exception ex) {
ex.printStackTrace();
}
System.out.println("Completed");
}
}
public class BigFileProcessor implements Runnable {
private final BlockingQueue<String> linesToProcess;
public BigFileProcessor (BlockingQueue<String> linesToProcess) {
this.linesToProcess = linesToProcess;
}
#Override
public void run() {
String line = "";
try {
while ( (line = linesToProcess.take()) != null) {
//do what you want/need to process this line...
if(line==BigFileReader.SENTINEL)
{
break;
}
String [] pieces = line.split("(...)/g");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I want to print the text "completed work" in BigFileWholeProcessor once all the thread work is done. But instead, it is not getting printed. Why is this? How to identify that all the threads are done and need printing?
shutdown() only signal ES to shutdown, you need
awaitTermination(long timeout, TimeUnit unit)
before print message
Use submit() method instead of execute(). The get() method can be used if you want to wait for the thread to finish at any point of time. Read documentation on use of Future object for further details.
ExecutorService es = Executors.newFixedThreadPool(2);
Future<?> f = es.submit(new Thread(new TestRun()));
f.get(); // Wait for result... (i.e similar to `join()` in this case)
es.shutdown(); // Shutdown ExecutorService
System.out.println("Done.");
I have defined a TestRun class implementing Runnable, not shown here. The Future object makes more sense in other scenarios.

How to achieve multi threading while one thread is at sleep mode

I have a problem where my class is performing the first run method after which it is not proceeding into a second, overidden run method.
The program execution beings in a controller class which has a main method and a thread pool:
public class RunnableController {
// Main method
public static void main(String[] args) throws InterruptedException {
try {
RunnableController controller = new RunnableController();
controller.initializeDb();
controller.initialiseThreads();
System.out.println("Polling");
} catch (Exception e) {
e.printStackTrace();
}
}
private void initialiseThreads() {
try {
threadExecutorRead = Executors.newFixedThreadPool(10);
PollingSynchronizer read = new PollingSynchronizer(incomingQueue, dbConncetion);
threadExecutorRead.submit(read);
} catch (Exception e){
e.printStackTrace();
}
}
}
My poller class which fetches new data and should do updating simulateously:
public class PollingSynchronizer implements Runnable {
public PollingSynchronizer(Collection<KamMessage> incomingQueue,
Connection dbConnection) {
super();
this.incomingQueue = incomingQueue;
this.dbConnection = dbConnection;
}
private int seqId;
public int getSeqId() {
return seqId;
}
public void setSeqId(int seqId) {
this.seqId = seqId;
}
// The method which runs Polling action and record the time at which it is done
public void run() {
int seqId = 0;
while (true) {
List<KamMessage> list = null;
try {
list = fullPoll(seqId);
if (!list.isEmpty()) {
seqId = list.get(0).getSequence();
incomingQueue.addAll(list);
this.outgoingQueue = incomingQueue;
System.out.println("waiting 3 seconds");
System.out.println("new incoming message");
Thread.sleep(3000);//at this wait I should execute run()
//when I debug my execution stops here and throws " Class not found Exception "
// its does not enters the message processor class
MessageProcessor processor = new MessageProcessor() {
//the run method which should fetch the message processor class.
final public void run() {
MessageProcessor(outgoingQueue).generate(outgoingQueue);
}
};
new Thread(processor).start();
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}
My message processor class:
public abstract class MessageProcessor implements Runnable {
private Connection dbConnection;
Statement st = null;
ResultSet rs = null;
PreparedStatement pstmt = null;
private Collection<KamMessage> outgoingQueue;
public KamMsg804 MessageProcessor(Collection<KamMessage> outgoingQueue,
Connection dbConnection) {
this.outgoingQueue = outgoingQueue;
this.dbConnection = dbConnection;
return (KpiMsg804) fetchedMessages;
}
public Collection<KamMessage> generate(Collection<KamMessage> outgoingQueue) {
while (true) {
try {
while (rs.next()) {
KamMessage filedClass = convertRecordsetToPojo(rs);
outgoingQueue.add(filedClass);
}
for (KamMessage pojoClass : outgoingQueue) {
KamMsg804 updatedValue = createKamMsg804(pojoClass);
System.out.print(" " + pojoClass.getSequence());
System.out.print(" " + pojoClass.getTableName());
System.out.print(" " + pojoClass.getAction());
System.out.print(" " + updatedValue.getKeyInfo1());
System.out.print(" " + updatedValue.getKeyInfo2());
System.out.println(" " + pojoClass.getEntryTime());
}
return outgoingQueue;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
My problem is exactly at the second run(9 method where I am getting exception in MessageProcessor class and it loops back to Polling.
How do I implement multithreading here, as when the thread sleeps for 3 seocnds in polling it should simultaneously update the database.
After which, how can the data be fed and updated back into the db.
My program flow - I have three classes:
1.Controller
2.PollerSynchro
3.Msgprocessor
I have database records, which are converted into POJO form and stored in a Collection. With these POJOs my classes try to do multiprocessing and updating in a single stretch.
Controller - has the thread pool, initiates poller class with poll method - done
Poller - should poll for new incoming messages and stores it in incoming queue - done
MsgProcessor - should look for new incoming messages and pass them from outgoing queue to incoming queue - also done
Problem:
Now my problem is
I have to implement this update while the poll thread sleeps for 3 sec,
In my code for the second void run() method in the Poller class, the outgoing queue is not passed and fed to the messageprocessor class for updating. My flow of execution only just loops back to first run method and am getting Class exception.
Please help me to solve these problems.
I can't sugar coat this, your code is a mess. However, as far as why your message processor code is not being executed, you never actually start the thread you created with this code:
MessageProcessor processor = new MessageProcessor() {
// the run method which should fetch the message processor class.
final public void run() {
MessageProcessor(outgoingQueue).generate(outgoingQueue);
}
};
Ignoring the confusingly named method being called, your code should look more like this:
Message processor = new MessageProcessor() {
// the run method which should fetch the message processor class.
final public void run() {
MessageProcessor(outgoingQueue).generate(outgoingQueue);
}
};
new Thread(processor).start();

Categories