Java - Stop thread from a different class - java

I'm trying to stop a java thread from a different class, but unable to figure out. I have looked into the below links, googled a lot from past 2 days but unable to nail down. May be a simple thing which i need to change but i'm out of options and hence posting it here.
Referred Links
java external threads (outside the class file it's used)
http://tutorials.jenkov.com/java-concurrency/creating-and-starting-threads.html
http://www.java2novice.com/java_thread_examples/
While typing the question, I referred the below links as well..
Stop a thread from outside
Below is my code sample. I'm able to start the WorkerThread from the MainThread and get into the loop. But unable to stop the thread started using the StopThread class.
I've also used the volatile option suggested in the below link.
http://tutorials.jenkov.com/java-concurrency/volatile.html
I feel I'm making a simple mistake, but not able to identify it.
//class WorkerThread
package main;
public class WorkerThread implements Runnable
{
public WorkerThread() {
isRunning = true;
}
public WorkerThread(boolean False) {
isRunning = False;
}
private volatile boolean isRunning;
public synchronized void stopThread() {
isRunning = false;
}
public synchronized boolean IsThreadRunning() {
return isRunning;
}
#Override
public void run()
{
int i = 1;
while(isRunning)
{
System.out.println("Loop " + i);
i++;
try { Thread.sleep(2000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
//class MainThread
package main;
public class MainThread
{
public static Thread t;
public static void main(String[] args)
{
t = new Thread(new WorkerThread());
t.start();
}
}
//class StopThread
package main;
public class StopThread
{
public static void main(String[] args)
{
//What should i write here to stop the thread started by MainThread
MainThread.t.interrupt();
}
}

public class MainThread
{
public static Thread t;
public static void main(String[] args)
{
t = new Thread(new WorkerThread());
t.start();
}
}
public class StopThread
{
public static void main(String[] args)
{
MainThread.t.interrupt();
}
}
It is not safe to call Thread.stop() it is listed as deprecated in JavaDocs
Also this may be just for the sake of this question, but why does your program have two main methods?

You have an opportunity to make use of what you defined volatile variable and gracefully come out of thread like below:
public class MainThread
{
public static WorkerThread workerThread;
public static void main(String[] args)
{
workerThread = new WorkerThread();
Thread t = new Thread(workerThread);
t.start();
}
}
public class StopThread
{
public static void main(String[] args)
{
Main.workerThread.stopThread();
}
}

Note: This solution works but not a perfect solution.
You can write and read value of isRunning variable from a properties file. This way you can have interaction between two different java processes. ThreadWorker just creates file upon initiation & and just makes attempt to read the file after that. StopThread modifies the properties file when triggered which should be picked up by ThreadWorker.
Check below example:
public class ThreadWorker implements Runnable
{
public volatile static boolean isRunning = false;
public ThreadWorker() {
Properties p = new Properties();
p.setProperty("isRunning", "1");
FileOutputStream out;
try {
//Writes all properties in appProperties file
out = new FileOutputStream("appProperties");
p.store(out, "---Thread Status----");
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run()
{
int i = 1;
String status = "1";
while("1".equals(status))
{
status = getStatus();
System.out.println("Loop " + i);
i++;
try { Thread.sleep(2000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
public String getStatus() {
FileInputStream in;
Properties p = new Properties();
try {
in = new FileInputStream("appProperties");
p.load(in);
return p.getProperty("isRunning");
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//class StopThread
public class StopThread
{
public static void main(String[] args)
{
Properties p = new Properties();
p.setProperty("isRunning", "0");
FileOutputStream out;
try {
out = new FileOutputStream("appProperties");
p.store(out, "---Thread Status----");
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//class StopThread
public class StopThread
{
public static void main(String[] args)
{
Properties p = new Properties();
p.setProperty("isRunning", "0");
FileOutputStream out;
try {
out = new FileOutputStream("appProperties");
p.store(out, "---Thread Status----");
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Make thread t a public member of class MainThread, and then just call MainThread.t.interrupt() from StopThread

Related

Synchronization is not working - new thread coming inside syncronization block instead of having lock on it

I am new to Multithreading, I am trying to Synchronize multiple request coming to method addRequestToPool,
New instance is created every time of class TicketRequestManagement and method addRequestToPool is called which will create thread and call further.
But it looks like when there are multiple request to addRequestToPool method which will further call synchronizeRequests the thread is not synchronized 2 thread will enter the code block instead of below synchronization code.
synchronized (this) {
while (hashMap.containsKey(docketNo)) {
wait();
}
hashMap.put(docketNo,1);
}
Below is the complete code
TicketRequestManagement :
public class TicketRequestManagement {
private static Logger logger = Logger.getLogger(TicketRequestManagement.class);
public SimpleActionResponse addRequestToPool(int docketNo) throws InterruptedException {
logger.info("addRequestToPool started with Docket No : " + docketNo);
SimpleActionResponse response = new SimpleActionResponse();
RequestSynchronization requestSynchronization = new RequestSynchronization(docketNo);
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
requestSynchronization.synchronizeRequests();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t1.join();
return response;
}
public SimpleActionResponse removeRequestFromPool(int docketNo) throws InterruptedException {
logger.info("removeRequestFromPool started with Docket No : " + docketNo);
SimpleActionResponse response = new SimpleActionResponse();
RequestSynchronization requestSynchronization = new RequestSynchronization(docketNo);
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
requestSynchronization.removeRequests();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
t2.join();
return response;
}
}
RequestSynchronization :
public class RequestSynchronization {
private static Logger logger = Logger.getLogger(RequestSynchronization.class);
private static ConcurrentHashMap<Integer, Integer> hashMap = new ConcurrentHashMap<>();
private int docketNo;
public RequestSynchronization(int docketNo) {
super();
this.docketNo = docketNo;
}
public void synchronizeRequests() throws InterruptedException {
synchronized (this) {
while (hashMap.containsKey(docketNo)) {
wait();
}
hashMap.put(docketNo,1);
}
}
public void removeRequests() throws InterruptedException {
synchronized (this) {
hashMap.remove(docketNo);
notify();
}
}
}
Can you please suggest what is the thing I am doing wrong here and I would also like to know the scope of variable docketNo for each request coming will it remain sync with it's thread even after it goes to wait or there is some effect on it.
Thank you in advance !!
Edit 1 :
I have changed my access level to class level Locking and sending class instance instead of docket Number, below is my Modified method code but it looks like notify is not working now don't know why :(
private final static Object lock = new Object();
public synchronized static void synchronizeRequests(RequestSynchronization requestSynchronization) throws InterruptedException {
while (hashMap.containsKey(requestSynchronization.getDocketNo())) {
lock.wait();
}
hashMap.put(requestSynchronization.getDocketNo(), requestSynchronization.getDocketNo());
}
public synchronized static void removeRequests(RequestSynchronization requestSynchronization) throws InterruptedException {
hashMap.remove(requestSynchronization.getDocketNo());
lock.notifyAll();
}

Can static variables ever be used to synchronize threads?

Below I have constructed an example which synchronizes three threads based on a static variable:
public class CallMethodsInOrder {
public static void main(String[] args) {
// Three instances of Thread, first calls first, second second and third third.
// Ensure that they are all called in order.
Thread first = new Thread(new FooRunner(new Foo(),MethodToCall.FIRST));
Thread second = new Thread(new FooRunner(new Foo(),MethodToCall.SECOND));
Thread third = new Thread(new FooRunner(new Foo(),MethodToCall.THIRD));
third.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
second.start();
first.start();
}
}
class Foo {
static boolean hasFirstRun = false;
static boolean hasSecondRun = false;
static boolean hasThirdRun = false;
public Foo() {
}
public void first() {
System.out.println("First");
hasFirstRun = true;
}
public void second() {
System.out.println("Second");
hasSecondRun = true;
}
public void third() {
System.out.println("Third");
hasThirdRun = true;
}
}
class FooRunner implements Runnable{
private Foo foo;
private MethodToCall method;
public FooRunner(Foo foo, MethodToCall method) {
this.foo = foo;
this.method = method;
}
#Override
public void run() {
if(method == MethodToCall.FIRST) {
foo.first();
}
else if (method == MethodToCall.SECOND){
while(!Foo.hasFirstRun) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
foo.second();
}
else if (method == MethodToCall.THIRD) {
while(!Foo.hasSecondRun) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
foo.third();
}
}
}
enum MethodToCall{
FIRST, SECOND, THIRD;
}
Is this a valid approach? I have read that static variables are not thread safe, however, cannot see a situation in which the above code would not execute the three methods in the desired order (first, second, third).
Many answers I have found have been related to accessing data structures with multiple threads vs ordering of methods as displayed here.
Since each static variable is only being modified by a single thread is it a problem?
As suggested in the comments, using synchronized is likely the way forward here. I feel the above code still works with static variables however is definitely not the best practise.
A related solution including Semaphores is included below:
public class CallMethodsInOrder2 {
public static void main(String[] args) {
// Three instances of Thread, first calls first, second second and third third.
// Ensure that they are all called in order.
// This approach uses Semaphore vs static variables.
Foo2 foo2 = new Foo2();
Thread first = new Thread(new FooRunner2(foo2,MethodToCall.FIRST));
Thread second = new Thread(new FooRunner2(foo2,MethodToCall.SECOND));
Thread third = new Thread(new FooRunner2(foo2,MethodToCall.THIRD));
third.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
second.start();
first.start();
}
}
class Foo2 {
private Semaphore one, two;
public Foo2() {
one = new Semaphore(1);
two = new Semaphore(1);
try {
one.acquire();
two.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void first() {
System.out.println("First");
one.release();
}
public void second() {
try {
one.acquire();
System.out.println("Second");
one.release();
two.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void third() {
try {
two.acquire();
two.release();
System.out.println("Third");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I think the static variable method 'works' in this case (for some value of 'works'), but is definitely less efficient.
You're sleeping an arbitrary amount of time in each thread ('100'), and then waking up to poll this variable. In the case of a semaphore, the OS takes care of the sleep/wake events to the threads.

Java - suspend thread until other thread event

I have an object A on which I'm updating some data every second and other objects B and C which want to use the data only once per update.
Every object work in parallel.
How can I make B and C wait for the update in A ?
I've seen some similar questions but their responses didn't help me.
I've seen that I could use a "synchronized" bloc on an object D, but they just put the bloc without telling how to instanciate or share that object.
The following code is what I use for my tests. I managed to get them working in parallel but I'm stuck with the suspending part.
This is the class for A
public class Master{
public static void main(String[] args) throws Exception {
Worker B = new Worker("B");
B.start();
Worker C = new Worker("C");
C.start();
while(true)
{
Thread.sleep(1000);
// update data
// notify every thread waiting that they can resume
}
}
}
This is the class used for B and C
public class Worker extends Thread
{
Worker(String name)
{
super("Worker " + name);
}
public void run()
{
int i = 0;
while(!this.isInterrupted())
{
// wait for A to update data
System.out.println(i);
i++;
}
System.out.println("thread interrupted");
}
}
From there, what do I need to add for the purpose I'm looking for ?
To do it very low level, only using the lang APIs, you should use wait/notifyAll.
Not that I used Main.class as an arbitrary object to synchronize
public class Main {
public static void main(String[] args) {
SharedData sharedData = new SharedData();
Worker w1 = new Worker("Worker 1", sharedData);
Worker w2 = new Worker("Worker 2", sharedData);
w1.start();
w2.start();
while (true) {
try {
Thread.sleep(1000);
sharedData.increase();;
System.out.println("Master: " + sharedData.value());
synchronized (Main.class) {
Main.class.notifyAll();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class SharedData {
private int data = 0;
public void increase () {
data++;
}
public int value() {
return data;
}
}
class Worker extends Thread {
private String workerName;
private SharedData sharedData;
public Worker(String workerName, SharedData sharedData) {
super();
this.workerName = workerName;
this.sharedData = sharedData;
}
#Override
public void run() {
while (true) {
try {
synchronized (Main.class) {
Main.class.wait();
}
System.out.println(workerName + ": " + sharedData.value());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Not sure if I understand you correctly, but this might be worth checking out for you:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html
Why use threads at all? Why not just do this?
public class Master {
public static void main(String[] args) {
Worker B = new Worker("B");
Worker C = new Worker("C");
while(true) {
Thread.sleep(1000);
updateData();
B.doWork();
C.doWork();
}
}
}
public class Worker
{
public void doWork() {
System.out.println(i);
i++;
}
private int i = 0;
}

Retrieve GPS DATA on a JTextArea with 2 different class

I have a a GPS receptor. I create a class to retrieve all the GPS data on my Eclipse Console.
(This is the code of makia42)
public class COM implements Runnable{
static Thread myThread=null;
static BufferedReader br;
static BufferedWriter wr;
static InputStreamReader isr;
static OutputStreamWriter osw;
static java.io.RandomAccessFile port;
public COM(){ /**Constructeur*/
myThread=new Thread(this);
}
public void start(){
try {
port=new java.io.RandomAccessFile("COM3","rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
}
catch (Exception e) {
System.out.println("start "+e.toString());
}
myThread.start();
}
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
public static void main(String[] args) {
COM temp= new COM();
temp.start();
}
}
I have another class which is a frame containing a button and a JTextArea. This class is in communication with my first class COM.
When i click the button, COM is starting and show me the data in my Eclipse Console.
But now, I'd like to show it on my JTextArea.
How can I do it ?
Best regards,
Tofuw
Take a moment to read about this pattern.
Make the Thread a Subject. Before starting register the instance of the class that contains the JTextArea as the Observer with the instance of the Thread. At the run() instead of printing on the console, use the notify(String);
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
Change to
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
notifyObservers(st); //Pass the data to the observers.
}
}
EDIT:
I suppose you can rewrite the Thread to a simple class. It will render the program unresponsive while it reads, that's why you have a Thread. I suppose you can implement a cleaner way using Future<String>
public class GpsReader {
public class GenericGPSException extends Exception {
public GenericGPSException(String message, Throwable cause) {
super(message, cause);
}
}
public static void main(String[] args) {
// Example of usage
GpsReader gpsReader = new GpsReader();
String messageFromDevice;
try {
// Try read it
messageFromDevice = gpsReader.getCoordinate();
} catch (GenericGPSException e) {
// Error, what does it says?
messageFromDevice = e.getMessage();
}
JTextArea mockArea = new JTextArea();
// Show to user anything that comes to it.
mockArea.setText(messageFromDevice);
}
private boolean isReady;
private RandomAccessFile port;
public GpsReader() {
}
public String getCoordinate() throws GenericGPSException {
if (!isReady) {
try {
port = new RandomAccessFile("COM3", "rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
isReady = true;
} catch (FileNotFoundException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
} catch (IOException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
}
}
try {
return port.readLine();
} catch (IOException e) {
throw new GenericGPSException("Error at reading the Device ", e);
}
}
}

How to tell main thread that part of thread job is done

Is it true that notify works only after thread is finished? In code below I can't get notification until I comment while (true). How to tell main thread that part of thread job is done?
public class ThreadMain {
public Thread reader;
private class SerialReader implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(3000);
synchronized(this) {
System.out.println("notifying");
notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
synchronized(d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
You should try to avoid using wait and notify with the newer versions of Java, as they're difficult to get right. Try using something like a BlockingQueue instead
public class ThreadMain {
public final BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
private class SerialReader implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(3000);
System.out.println("notifying");
queue.offer(Boolean.TRUE);
System.out.println("notifying done");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
try {
d.queue.take(); // block until something is put in the queue
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
If you want to be notified when the Thread t completes, call t.join() in the calling Thread. This will block until t has finished its Runnable.
As user oddparity noted in the comments, you are calling wait() and notify() on different objects. A possible fix for this would be to make your SerialReader extend Thread rather than implement Runnable and then assigning reader to be a new instance of the SerialReader directly. :
public class ThreadMain {
public Thread reader;
private class SerialReader extends Thread {
public void run() {
while (true) {
try {
Thread.sleep(3000);
synchronized(this) {
System.out.println("notifying");
notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new SerialReader();
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
synchronized(d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
If you want to use Runnable with wait()/notify() you can do it this way :
public class ThreadMain {
public Thread reader;
private class SerialReader implements Runnable {
public void run() {
Thread thisThread = Thread.currentThread();
while (true) {
try {
Thread.sleep(3000);
synchronized (thisThread) {
System.out.println("notifying");
thisThread.notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String[] args) {
ThreadMain d = new ThreadMain();
d.reader.start();
synchronized (d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}

Categories

Resources