I have this code:
public class classExample implements Observer Runnable {
public classExample() {
//...
}
#Override
public void run() {
while (true) {
//wait for EVENT;
//do something;
}
}
#Override
public void update(Observable arg0, Object arg1) {
//signal EVENT;
}
}
Basically, i want my thread to do something every time the update() method is called. I can't do in the update() method itself cause it would be executed in the same thread of the Observable calling notifyObservers().
Are there any ways to "signal" an event to the run() method?
You could implement message passing via blocking concurrent queues. The classExample thread could then wait blocking for new messages to be sent via the queue. This thread could then execute the stuff you originally wanted to execute in the update method, when a new message comes.
While the blocking queue as suggested by others would work, I'm not a big fan of it because it requires a busy wait (the consumer loops infinitely polling for a message). An alternative would be to submit a task every time the Observer receives a notification.
public class Main extends Observable implements Observer {
private final int numCores = Runtime.getRuntime().availableProcessors();
private final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numCores);
public Main() {
addObserver(this);
}
public static void main(String[] args) throws InterruptedException {
new Main().execute();
}
private void execute() {
for (int i = 0; i < 5; ++i) {
this.setChanged();
this.notifyObservers(i);
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
#Override
public void update(Observable o, Object arg) {
System.out.printf("Received notification on thread: %s.\n", Thread.currentThread().getName());
executor.submit(() -> System.out.printf("Running in thread: %s, result: %s.\n",
Thread.currentThread().getName(), arg));
}
}
Output:
Received notification on thread: main.
Running in thread: pool-1-thread-1, result: 0.
Received notification on thread: main.
Running in thread: pool-1-thread-2, result: 1.
Received notification on thread: main.
Running in thread: pool-1-thread-3, result: 2.
Received notification on thread: main.
Running in thread: pool-1-thread-4, result: 3.
Received notification on thread: main.
Running in thread: pool-1-thread-5, result: 4.
If you extend the thread class, you can override its methods and then you can just use super() and then do whatever code you want
At the very basic elements: Why not just use some membervariable/flag that you set in your update-Method?
eventWasFired = true;
In your while-loop inside of run() do something like:
try {
Thread.sleep(updateTimer);
if(eventWasFired) {
doSomeAction();
eventWasFired = false;
}
} catch (InterruptedException ie) {
// handle if you like
}
you need to synchronize access and use some atomic-variable if you have multiple threads that may access your observable. Otherwise your program is exposed to data races.
Related
I need a thread that will only run once at a time, for example if it's called for the first time it will run, if it is called a second time, the first should stop completely and be allowed to die and a new one should take it's place.
I was ran a small test to see what was actually happening between each execution, the results show that the thread doesnt die but instead two threads are being executed alongside:
public class Test {
Worker worker = new Worker();
#Override
public void valid() {
try {
if (worker.running) {
worker.running = false;
worker.join();
}
} catch (InterruptedException iex) {
worker.running = false;
}
worker = new Worker();
worker.start();
}
private final class Worker extends Thread {
private volatile boolean running = true;
#Override
public void run() {
while (running) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException iex) {
Thread.currentThread().interrupt();
}
}
}
}
}
The results are as follows:
//Upon first execution
Thread-4
Thread-4
Thread-4
Thread-4
//When I execute it again
Thread-7
Thread-4
Thread-7
Thread-4
Thread-7
Thread-4
I've tried using ExecutorService or using while(!Thread.currentThread.isInterrupted) instead of the boolean flag, and got the same results.
How can I properly stop "Thread-4" and have only one of them running?
The actual issue comes from a thread that will cycle through a list and update things on discord chat by request, what the thread does is listen to input and change as suggested by kidney I'm trying to use executor.submit() and Future
private ExecutorService executor = Executors.newSingleThreadExecutor();
private Future<Void> worker;
private void setupImageThread() {
if (!worker.isDone() && !worker.isCancelled()) {
worker.cancel(true);
}
this.worker = (Future<Void>)executor.submit(new Cycler(Listener.queue(), this.links, Cel.cMember()));
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
Runnable timeout = () -> {
executor.shutdown();
};
ses.schedule(timeout, 100, TimeUnit.SECONDS);
}
How can I go about initializing the Future for the first time it is created?
Using single thread executor service, I would try something like this:
public class Test {
private static ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> worker;
public Test() {
this.worker = executor.submit(new Worker());
}
#Override
public void valid() {
if (!worker.isDone() && !worker.isCancelled()) {
worker.cancel(true); // Depends on whether you want to interrupt or not
}
this.worker = executor.submit(new Worker());
}
}
And make Worker implement Runnable.
It seems that the method valid can be called several times simultaneously. That means, every of those calls will wait to end only for one thread (Worker), whereas, every of them creates its own Worker and you lose a pointer to it, so it impossible to stop bunch of new created workers.
You should make the valid method synchronized: synchronized void valid() it will prevent creating many workers:
#Override
synchronized public void valid() {
...
}
One more thing to say. You put the while loop outside the try-catch, which is wrong: if the tread gets interrupted, the interruption doesn't kill it, because next interation gets started, so it should be like that:
#Override
public void run() {
try {
while (running) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(2000);
}
catch (InterruptedException iex) {
//you don't need here Thread.currentThread().interrupt() call, because the thread has alredy been interrupted.
// The return statement here is also obsolete, I just use it as an example, but you can use empty braces.
return;
}
}
}
I have the following method, that called every time I click over a button, this results to start a new thread again and again when the button is pressed, that results to multiple initialisation of thread, however I want only one thread should get executed, how can I achieve this.
private void scheduleMessages() {
new Thread(new Runnable() {
#Override
public void run() {
//Some operations
}
}).start();
}
Note: this is a small method and I don't want to create a separate class, just to make it singleton, so a solution without singleton pattern will be appreciated.
if you cannot make instance of this to check isActive() you should make a semaphore variable - a boolean, that you set to true when you start thread and set to false when you are done.
private void scheduleMessages() {
if (!taskRunning){
new Thread(new Runnable() {
#Override
public void run() {
taskRunning = true;
//Some operations
taskRunning = false;
}
}).start();
}
}
Have that thread be a background thread - maybe initialize it when the button is pressed the first time.
Have that thread listen to a queue - and act upon messages in that queue.
Whenever the button is pressed again, put a new message into the queue.
If your need to execute every requests but on a specific number of threads, you can use a thread pool and let the executor manage the queue .
private ExecutorService services;
private final static int POOL_SIZE = 1;
public MessagesService(){
services = Executors.newFixedThreadPool(POOL_SIZE);
}
public void scheduleMessages(Runnable r){
services.submit(r);
}
If you call addCall x times, x thread will be executed at the end but will never use more than the number of thread available in the pool. Here, 1 thread.
For a system that only accept one request, you can use the same approch but check the Future returned by a single thread executor. That way, you can check the status of the service.
private ExecutorService services;
private Future<?> lastCall;
public MessagesService() {
services = Executors.newSingleThreadExecutor();
lastCall = null;
}
public synchronized void scheduleMessages(Runnable r) {
if(!isScheduled()){
lastCall = services.submit(r);
}
}
public boolean isScheduled(){
return lastCall != null && !lastCall.isDone();
}
That way, the Runnable doesn't need to update a flag, which give a reusable solution.
Here is a sample of the Runnable to test these codes :
new Runnable() {
System.out.println("Running");
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
I don't know how to make for a thread to run until the task is finished.
So i have this class:
public class MainTest {
public static void main(String[] args){
ThreadRunnable t1 = new ThreadRunnable();
Thread t2 = new Thread(t1);
t2.start();
System.out.println(3);
//here the next code to run
}
}
And another that try for example to add data in database:
public class ThreadRunnable implements Runnable{
public void run(){
//code to make the thread waits until the insert is done
//code for inserting data in database
}
}
So, inside method run() i want something like:
- try to insert data in database
- if connection to database is down, wait 5 seconds and try again
- if connection is ok, then insert data, and return successful message that data is added
Is this possible, and if yes, how?
Thanks!
You don’t need to wait for a thread. Just do the retries in a loop in your Runnable:
public void run() {
try {
while (true) {
try {
// Do database operations here
// Succeeded
break;
} catch (SQLException e) {
// Failed; log exception and try again.
logger.log(Level.INFO, "Couldn't save data.", e);
}
// Wait before trying again.
Thread.sleep(5000);
}
} catch (InterruptedException e) {
logger.log(Level.INFO, "Interrupted; exiting.", e);
}
}
Note: An interrupt is an explicit request for a thread to stop what it’s doing and self-terminate. The InterruptedException should not be caught inside the loop, because you want the loop to terminate in the event of an interrupt.
On the other hand, you do want the loop to keep executing in the event of an SQLException, so it should be caught inside the loop.
You can do something like that :
1) Add a waitFor function in your ThreadRunnable
2) Add synchronization via un LOCK variable
The code :
public class ThreadRunnable implements Runnable{
private boolean ended=false;
private final Object LOCK=new Object();
public void run(){
// do my stuff...
...
//at the end, notify the thread waiting for : it will wake up
synchronized(LOCK)
{
ended=true;
LOCK.notifyAll();
}
}
/**
Waits until the task is done
*/
public void waitFor()
{
synchronized(LOCK)
{
while(!ended)
{
//sleeps until notifAll is called (see run())
wait();
}
}
}
}
(in this code, you have to add the try/catch for the InterruptedException)
In your main :
public class MainTest {
public static void main(String[] args){
ThreadRunnable t1 = new ThreadRunnable();
Thread t2 = new Thread(t1);
t2.start();
t1.waitFor();
System.out.println(3);
//here the next code to run
}
}
This is a general Java question and not an Android one first off!
I'd like to know how to run code on the main thread, from the context of a secondary thread. For example:
new Thread(new Runnable() {
public void run() {
//work out pi to 1,000 DP (takes a while!)
//print the result on the main thread
}
}).start();
That sort of thing - I realise my example is a little poor since in Java you don't need to be in the main thread to print something out, and that Swing has an event queue also - but the generic situation where you might need to run say a Runnable on the main thread while in the context of a background thread.
EDIT: For comparison - here's how I'd do it in Objective-C:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0UL), ^{
//do background thread stuff
dispatch_async(dispatch_get_main_queue(), ^{
//update UI
});
});
Thanks in advance!
There is no universal way to just send some code to another running thread and say "Hey, you, do this." You would need to put the main thread into a state where it has a mechanism for receiving work and is waiting for work to do.
Here's a simple example of setting up the main thread to wait to receive work from other threads and run it as it arrives. Obviously you would want to add a way to actually end the program and so forth...!
public static final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
public static void main(String[] args) throws Exception {
new Thread(new Runnable(){
#Override
public void run() {
final int result;
result = 2+3;
queue.add(new Runnable(){
#Override
public void run() {
System.out.println(result);
}
});
}
}).start();
while(true) {
queue.take().run();
}
}
In case you are on Android, using a Handler should do the job?
new Handler(Looper.getMainLooper()).post(new Runnable () {
#Override
public void run () {
...
}
});
An old discussion, but if it is a matter of sending request to the main thread (an not the opposite direction) you can also do it with futures. The basic aim is to execute something in background and, when it is finished, to get the result:
public static void main(String[] args) throws InterruptedException, ExecutionException {
// create the task to execute
System.out.println("Main: Run thread");
FutureTask<Integer> task = new FutureTask<Integer>(
new Callable<Integer>() {
#Override
public Integer call() throws Exception {
// indicate the beginning of the thread
System.out.println("Thread: Start");
// decide a timeout between 1 and 5s
int timeout = 1000 + new Random().nextInt(4000);
// wait the timeout
Thread.sleep(timeout);
// indicate the end of the thread
System.out.println("Thread: Stop after " + timeout + "ms");
// return the result of the background execution
return timeout;
}
});
new Thread(task).start();
// here the thread is running in background
// during this time we do something else
System.out.println("Main: Start to work on other things...");
Thread.sleep(2000);
System.out.println("Main: I have done plenty of stuff, but now I need the result of my function!");
// wait for the thread to finish if necessary and retrieve the result.
Integer result = task.get();
// now we can go ahead and use the result
System.out.println("Main: Thread has returned " + result);
// you can also check task.isDone() before to call task.get() to know
// if it is finished and do somethings else if it is not the case.
}
If your intention is to do several stuff in background and retrieve the results, you can set some queues as said above or you can split the process in several futures (starting all at once or starting a new one when needed, even from another future). If you store each task in a map or a list, initialized in the main thread, you can check the futures that you want at anytime and get their results when they are done.
You may want to use the 'even dispatching thread' where most event driven things happen. If you are using swing then:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Your code here.
}
});
Or create a class that implements Runnable and pass it into invokeLater().
If you're using JavaFX, which I highly recommend, then you can use
Platform.runLater(new Runnable() {
#Override
public void run() {
alert(text);
}
});
from within your non-UI thread, and the runnable will executed from the UI thread on return from your thread.
A little late to the party but I think that my approach is a little bit different.
Modifying Affe's solution a little bit
public static final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
public static void main(String[] args) {
Thread myThread = new Thread(
() -> {
String name = Thread.currentThread().getName();
System.out.println("initial current thread " + name);
queue.add(() -> System.out.println(Thread.currentThread().getName()));
});
myThread.setName("background thread");
myThread.start();
try {
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
while (!queue.isEmpty()) {
try {
queue.take().run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
output
initial current thread background thread
main
I have a ThreadManager with two Threads. One for gui-relevant requests and one for measurement-relevant requests. The are both running and checking their queue of requests, if there is any, they are processing the request. One can add requests at any time, using the static ThreadManager.addGuiRequest(eGuiRequest) and ThreadManager.addMeasRequest(eMeasRequest) methods. Now both of those need to be initialized which is done by adding a INIT request to the corresponding queue. But the initialization of the measurement is depending on the fact that the gui is already initialized. I tried to solve this using wait()/notify(), but I can not get it working.
Here is a SSCCE. At startup, both queues have a INIT request added and are then started. The measurement initialization detects that the gui is not yet initialized and perfomrs a wait(). The gui initializes (simulated by sleeping for 5s). This all works fine.
After the gui initialized, it tries to wake up the measurement thread, but the measurement thread does not wake up... I based my wait()/notify() code on this article. What is going wrong here?
import java.util.LinkedList;
import java.util.NoSuchElementException;
public class ThreadManager {
public static void main(String[] args) {
new ThreadManager();
ThreadManager.addMeasRequest(eMeasRequest.OTHER_STUFF);
}
public enum eGuiRequest { INIT, OTHER_STUFF; }
public enum eMeasRequest { INIT, OTHER_STUFF; }
private static LinkedList<eGuiRequest> guiQueue = new LinkedList<eGuiRequest>();
private static LinkedList<eMeasRequest> measQueue = new LinkedList<eMeasRequest>();
private static Thread guiThread, measThread;
protected boolean initialized = false;
public ThreadManager() {
final int waitMs = 200;
guiThread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
if (guiQueue.isEmpty()) sleepMs(waitMs);
else {
eGuiRequest req = guiQueue.getFirst();
processGuiRequest(req);
guiQueue.removeFirst();
}
} catch (NoSuchElementException e) {}
}
}
private void processGuiRequest(eGuiRequest req) {
System.out.println("T: " + "Processing Gui request: " + req);
switch (req) {
case INIT:
// do some initializiation here - replaced by a wait:
sleepMs(5000);
System.out.println("I: " + "guiThread finished, waking up measThread");
synchronized (measThread) {
initialized = true;
measThread.notify();
}
break;
case OTHER_STUFF:
// do other stuff
break;
}
}
});
measThread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
if (measQueue.isEmpty()) sleepMs(waitMs);
else {
eMeasRequest req = measQueue.getFirst();
processMeasurementRequest(req);
measQueue.removeFirst();
}
} catch (NoSuchElementException e) {}
}
}
private void processMeasurementRequest(eMeasRequest req) {
if (req == eMeasRequest.INIT) { // if init, wait until GUI is initialized
synchronized (this) {
while (!initialized) {
System.out.println("I: " + "measThread waits for guiThread to finish initializiation");
try {
wait();
} catch (Exception e) {}
System.out.println("I: " + "measThread awakes");
}
}
}
System.out.println("T: " + "Processing Measurement request: " + req);
// process request here:
sleepMs(5000);
}
});
addGuiRequest(eGuiRequest.INIT);
addMeasRequest(eMeasRequest.INIT);
guiThread.start();
measThread.start();
}
public static void sleepMs(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException ee) {}
}
public static void addGuiRequest(eGuiRequest req) {
guiQueue.add(req);
}
public static void addMeasRequest(eMeasRequest req) {
measQueue.add(req);
}
}
The GUI thread calls notify() on measThread (of type Thread), and the processMeasurementRequest() method calls wait() on this, which is the Runnable instance used by measThread.
I would advise using a specific object, shared by both threads to wait and notify:
private static final Object GUI_INITIALIZATION_MONITOR = new Object();
Also, instead of using a LinkedList and sleeping an aritrary time between requests, I would use a BlockingQueue: this would allow the consuming thread to handle a request as soon as there is one, and would avoid unnecessary wakeups from the sleeping state.
Also, instead of the low-level wait/notify, you could use a CountDownLatch initialized to 1. The GUI thread would countDown() the latch when it's initialized, and the mesurement thread would await() the latch until the GUI thread has called countDown(). This would delegate complex synchronization and notification stuff to a more high-level, well-tested object.
The main problem is that you call notify() on measThread, but wait() is called on an anonymous class. The easiest way to fix this is to create a special object for synchronization. For example, you create a field:
private static final Object LOCK = new Object();
Then you write synchronized blocks using this object and call its methods like this:
synchronized (LOCK) {
while (!initialized) LOCK.wait();
}
Also I have to say that this piece of code doesn't use any synchronization at all for the fields accessed from different threads, which means that it can break at any time. Both queues are accessed outside the threads created by you, this means that you should either access them with a lock held all the time, or you can make them thread safe by using a built-in synchronized list:
quiQueue = Collections.synchronizedList(new LinkedList<eGuiRequest>());
initialized is accessed from synchronized blocks, but right now they synchronize on different locks (I have described this problem at the start of my answer). If you fix this problem, initialized will also be working as it should.
Just do not sent init request to measurment at startup. Sent it from processGuiRequest() after execution of init gui request. Then no wait/notify stuff is needed.