I'm new to RX and i don't know how the schedulers work. below is some code that never run onComplete . but if i put a while(true) loop at the end it works correctly. it seams the app will exit before running new thread.
why is this happening? and how to fix this issue?
Subscriber<String> subscriber = new Subscriber<String>() {
#Override
public void onCompleted() {
System.out.println("done");
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onNext(String o) {
System.out.println(o);
}
};
Observable.from(new String[]{"1", "2", "3","4"}).
subscribeOn(Schedulers.immediate())
.observeOn(Schedulers.newThread())
.subscribe(subscriber);
Just add Thread.sleep(1000); as the last statement if your program exits too early.
As to why this happens.
This answer quotes:
The Java Virtual Machine continues to execute threads until either of the following occurs:
...
All threads that are not daemon threads have died ...
Now if we look at RxThreadFactory that produces threads for Schedulers:
public final class RxThreadFactory extends AtomicLong implements ThreadFactory {
...
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, prefix + incrementAndGet());
t.setDaemon(true);
return t;
}
}
So a more complex solution would be to use Schedulers.from() and pass in a custom Executor with your own ThreadFactory that produces non-daemon threads.
Related
I have made a class called AbortableThread that is supposed to start and stop a thread when I want to. The class is relatively small since it just contains this code :
public class AbortableThread implements Runnable
{
private Thread worker;
private Runnable target;
public AbortableThread(Runnable target)
{
this.target = target;
}
public void start()
{
worker = new Thread(this);
worker.start();
}
public void stop()
{
worker.interrupt();
}
public void run()
{
while (!worker.isInterrupted())
target.run();
}
}
However, calling stop() does not stop the Thread. I think that's because target.run() runs on a separate thread, but I have no clue.
There isn’t a good way to stop a Runnable from outside (as a last resort there is stop, but that isn’t a good way).
A Runnable needs to be a good citizen and check for interruption itself, using Thread.currentThread().isInterrupted().
If the Runnable catches InterruptedException, the interrupt flag will be cleared; the Runnable needs to restore the interrupt flag by calling interrupt on the current thread.
In the posted code what happens is that the Runnable executes on the worker thread and the worker never gets a chance to check the interruption flag until the Runnable completes. Assuming the Runnable is something like
() -> { try {
Thread.sleep(100000L):
} catch (InterruptedException e) {}}
then the sleep would be cut short when the worker is interrupted, but the interrupt flag would be cleared so the Runnable would be executed again in the next iteration of the loop.
Try something like this:
public class AbortableThread implements Runnable
{
private final AtomicBoolean running = new AtomicBoolean(false);
private Thread worker;
private Runnable target;
public AbortableThread(Runnable target)
{
this.target = target;
}
public void start()
{
worker = new Thread(this);
worker.start();
}
public void stop()
{
running.set(false);
}
public void run()
{
running.set(true);
while (running.get()) {
try {
// make an small sleep
Thread.sleep(1);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.out.println(
"Thread was interrupted, Failed to complete operation");
}
// do something here like the one in question; it must be none-blocking
target.run();
}
}
}
A complete example can be found here:
How to Kill a Java Thread
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;
}
}
}
Is there a way I can do a similar task like the android OS or java AWT thread where a task is run on a particular thread regardless of which thread of which thread the method was called from e.g. repaint().
private Thread thread;
public void startThread(){ //method which start's my thread
thread = new Thread(new Runnable(){
doSomething();
});
thread.start()
}
public void submitTask(Runnable runnable){
//run the runnable task on the thread "thread"
}
How can I achieve something like this, on a situation where I have more then one active thread
How I've dealt with this scenario before is to create a work queue and a thread which processes tasks that get added to it. So any thread can add a work item to the queue and the same thread will process it regardless of what thread added the work item.
public class MyClass {
private LinkedBlockingQueue<MyTask> myTaskProcessingQueue;
public MyClass() {
myTaskProcessingQueue = new LinkedBlockingQueue<MyTask>();
new MyTaskWorker().start();
}
public void processTask(MyTask myTask) {
myTaskProcessingQueue.put(myTask);
}
private class MyTaskWorker extends Thread {
#Override
public void run() {
while (true) {
try {
processMyTask(myTaskProcessingQueue.take());
} catch (InterruptedException ie) {
// handle it
}
}
}
private void processMyTask(MyTask myTask) {
// do work
}
}
}
I have a GUI program that executes TestNG automation scripts. It's meant for users to easily configure some setting and launch the automation script that they want.
One thing I need to add is the ability to instantly stop the running TestNG process. Something like how in Eclipse, the 'Terminate' button will instantly stop whatever is running.
This is what the code that launches the TestNG tests looks like:
public class ScriptRunner implements Runnable {
public void runScript() {
Thread testRun = new Thread(this);
testRun.start();
}
#Override
public void run() {
//various other things are configured for this,
//but they're not relevant so I left them out
TestNG tng = new TestNG();
//While this runs, various browser windows are open,
//and it could take several minutes for it all to finish
tng.run();
}
}
As per the comment, the tng.run() can take several minutes to complete, and it's performing several things, opening/closing browser windows, etc.
How can I just instantly terminate the process, like you would when running an application from an IDE?
EDIT:
Per the comments, I'm attempting to use a ServiceExecutor and shutDownNow() The code is looking like this:
ExecutorService executorService = Executors.newFixedThreadPool(10);
public void runScript() {
executorService.execute(this);
}
//this method gets called when I click the "stop" button
public void stopRun() {
executorService.shutdownNow();
}
#Override
public void run() {
//same stuff as from earlier code
}
Spawn a child JVM process using ProcessBuilder or Runtime and you will be able to terminate that process when the user requests that the script stops running.
You can use ExecutorService to start test execution into one another thread. You can choose to have many thread in parrallel or juste one thread for all tests in sequence by choosing which executor service you need.
After that, start the execution of all tests in the same executor service instance by calling submit() method on it. You can stop the execution of all submitted runnables by calling shutdownNow() method.
It is important to use the same instance of ExecutorService, otherwise you start each test in a different thread and you will not enable to break the execution chain (or by calling shutdownNow() on all of them).
I was recently working on the executor framework. Here I have listed my problem
http://programtalk.com/java/executorservice-not-shutting-down/
Be careful if you are doing some IO operations the executor service may not shutdown immediately. If you see the below code stopThread is important because it tells your program that the thread has been asked to stop. And you can stop some iteration what you are doing.
I will modify your code like this:
public class MyClass {
private ExecutorService executorService;
private boolean stopThread = false;
public void start() {
// gives name to threads
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("thread-%d").build();
executorService = Executors.newSingleThreadExecutor(factory);
executorService.execute(new Runnable() {
#Override
public void run() {
try {
doTask();
} catch (Exception e) {
logger.error("indexing failed", e);
}
}
});
executorService.shutdown();
}
private void doTask() {
logger.info("start reindexing of my objects");
List<MyObjects> listOfMyObjects = new MyClass().getMyObjects();
for (MyObjects myObject : listOfMyObjects) {
if(stopThread){ // this is important to stop further indexing
return;
}
DbObject dbObjects = getDataFromDB();
// do some task
}
}
public void stop() {
this.stopThread = true;
if(executorService != null){
try {
// wait 1 second for closing all threads
executorService.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
What about this,
add a volatile static boolean and make the thread code look like...
if(ScriptRunner.runThread){
//Do some stuff here
}
if(ScriptRunner.runThread){
//Do some other stuff here
}
if(ScriptRunner.runThread){
//Do some other stuff here
}
if(ScriptRunner.runThread){
//Do rest of the stuff here
}
Now you can add a button in your main GUI that simply sets the runThread to false so the thread will terminate nearly instant leaving all the leftover code untouched as you press the Stop button.
public class ScriptRunner implements Runnable {
volatile static Boolean runThread = true;
public void runScript() {
Thread testRun = new Thread(this);
testRun.start();
}
public void terminate(){
runThread = false;
}
#Override
public void run() {
//various other things are configured for this,
//but they're not relevant so I left them out
TestNG tng = new TestNG();
//While this runs, various browser windows are open,
//and it could take several minutes for it all to finish
tng.run();
}
}
How about a new Thread? You have to add an private Thread thread; in the gui and when ever you start
thread = new thread(){
#Override
public void run(){
//start process here
}
};
thread.start();
and to stop "terminate"
thread.stop();(depracted) or thread.setDeamon(true);
Everytime I have to stop a process by the gui I use this.
Hope I could help ;)
In your GUI somewhere you have something like
ScriptRunner scriptRunner = new ScriptRunner();
scriptRunner.runScript();
When you want to stop it call
scriptRunner.interrupt();
Change the code in ScriptRunner
private Thread testRun;
public void runScript() {
testRun = new Thread(this);
testRun.start();
}
public void interrupt() {
testRun.interrupt();
}
Save all created processes and kill them when your program ends:
public class ProcessFactory {
private static Set<Process> processes = new HashSet<>();
private static boolean isRunning = true;
public static synchronized Process createProcess(...) throws ... {
if (!isRunning)
throw ...
... // create your spawned process
processes.add(process);
return process;
}
public static synchronized void killAll() {
isRunning = false;
for (Process p : processes)
p.destroy();
processes.clear();
}
public static void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
void run() {
killAll();
}
});
}
}
This can be improved by adding a mechanism that removes already dead processes, but you get the general idea.
I have a JRuby engine which evaluates some scripts and I want to close the thread if it takes more than 5 seconds.
I tried something like this:
class myThread extends Thread{
boolean allDone = false;
public void threadDone() {
allDone = true;
}
public void run() {
while(true) {
engine.eval(myScript);
if(allDone)
return;
}
}
(...)
th1 = new myThread();
th1.start();
try {
Thread.sleep(5000);
if(th1.isAlive())
th1.threadDone();
} catch(InterruptedException e) {}
if(th1.isAlive())
System.out.println("Still alive");
I also tried to kill the thread with th1.stop() or th1.interrupt() but the value retured by th1.isAlive() method is always true.
What can I do?
I want to add that myScript could be "while(1) do; end" and I cannot wait until it's completed. So I want to prevent scripts like that and kill the thread if it takes more than 5 seconds.
Another solution would be to use the built-in mechanism to interrupt threads:
public void run() {
while (!Thread.currentThread().isInterrupted()) {
engine.eval(myScript);
}
}
...
th1 = new myThread();
th1.start();
try {
Thread.sleep(5000);
th1.interrupt();
}
This way, no need for an allDone field, and no risk in failing to synchronize.
To make your Thread stoppable you might want something like.
class MyTask implements Runnable {
public void run() {
try {
engine.eval(myScript);
} catch(ThreadDeath e) {
engine = null; // sudden death.
}
}
}
You can call Thread.stop(), but I suggest you read the warnings on this method first.
If you want a thread to run for up to 5 seconds, the simplest solution is for the thread to stop itself.
class MyTask implements Runnable {
public void run() {
long start = System.currentTimeMillis();
do {
engine.eval(myScript);
} while(System.currentTimeMillis() < start + 5000);
}
}
This assumes you want to run engine.eval() repeatedly. If this is not the case you may have to stop() the thread. It is deprecated for a good reason but it might be your only option.