Java: cannot exit from a custom RunLoop implementation - java

I am trying to create a custom run loop that basically run tasks in a FIFO order and provides three APIs: addTask(Task task), run() and exit()
Task Interface
public interface Task {
public void perform();
public boolean isDone();
public boolean isStarted();
}
Task RunLoop
public class TaskRunLoop {
private Queue<Task> q;
private boolean isRunning;
public TaskRunLoop() {
q = new LinkedList<>();
isRunning = true;
// run();
}
public void addTask(Task t) {
q.offer(t);
}
public void run() {
while(isRunning()) {
while (q.size() > 0) {
Task t = q.poll();
t.perform();
}
}
}
public void exit() {
isRunning = false;
q.removeAll(q);
System.exit(0);
}
public boolean isRunning() {
return isRunning;
}
public static void main(String[] args) {
TaskRunLoop looper = new TaskRunLoop();
for (int i = 0; i < 10; i++) {
looper.addTask(new TaskImpl("task " + i));
}
looper.run();
looper.exit();
System.out.println("still running? " + looper.isRunning());
}
}
The tasks 0 - 9 can be run successfully, but the exit() call does not kill the run loop. I guess that while-loop in the run() method runs infinitely, I was wondering how to exit that while loop. Thanks!

looper.run(); is not a asynchronous call.
So the execution stays indeed stuck on looper.run(); and never reaches looper.exit();.
To prevent it, you could make your class extends Thread.
Which allows to invoke looper.run(); in a separate thread from the main thread that invokes it.
To start the thread, you should invoke start() and not run() (that is a specific method of Thread) :
public static void main(String[] args) {
TaskRunLoop looper = new TaskRunLoop();
for (int i = 0; i < 10; i++) {
looper.addTask(new TaskImpl("task " + i));
}
looper.start(); // instead of run()
looper.exit();
System.out.println("still running? " + looper.isRunning());
}

Related

I expect infinite loop,but not,why?

code like this
for test two case
one is have volatile keywords ,can stop
other is without volatile,the thread infinite loop
public class VolatileTest extends Thread {
public boolean flag = false;
public static void main(String[] args) throws InterruptedException {
VolatileTest volatileTest = new VolatileTest();
volatileTest.start();
Thread.sleep(1000);
volatileTest.flag = true;
}
#Override
public void run() {
while (!flag) {
System.out.println("=====>");
}
}
}
My mistake. The problem is that you are calling a synchronized method inside your while loop. Try it like this. Stopped will never print unless you redeclare flag as volatile.
public class VolatileTest extends Thread {
public boolean flag = false;
public static void main(String[] args) throws InterruptedException {
VolatileTest volatileTest = new VolatileTest();
volatileTest.start();
Thread.sleep(1000);
volatileTest.flag = true;
System.out.println("flag is now " + flag);
}
#Override
public void run() {
int i = 0;
while (!flag) {
i++;
}
System.out.println("stopped");
}
}

Assign a task to Thread and return from method. for example

public class MyThreadExample {
public static void main(String[] args) {
MyThreadExample myThreadExample = new MyThreadExample();
String country= myThreadExample.getCountry();
System.out.println(country);
}
public String getCountry() {
/* Question : */
return "India";
}
public void printValues() {
for(int i = 0 ; i < 200; ++i) {
System.out.println(i);
}
}
}
Label Question : I want call printValues() method and immediatly return from this method, can I use Thread here to call printValue()
The simplest way to run some code in a new thread, assuming you have a Java 8 compiler:
new Thread(() -> {
printValues();
}).start();
or assuming you don't have a Java 8 compiler:
new Thread() {
#Override
public void run() {
printValues();
}
}).start();
Note, however, that this might not do what you want.
(Some people will recommend using an Executor; when you only have one task to run, there is no difference in behaviour, but the Executor would add more complexity)
You need to use 'Futures'.
See 'Futures and Callables' here
Yes you can surely use Threads , I prefer ExecutorService mechanism ,
Here is how you do it :
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Runnable() {
public void run() {
for(int i = 0 ; i < 200; ++i) {
System.out.println(i);
}
}
});
executorService.shutdown();
You could rewrite your printValues() method this way to start a thread inside the method for the execution of what you want.
public void printValues() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0 ; i < 200; ++i) {
System.out.println(i);
}
}
});
t.start();
}

wait and notify with condition Java

I am using wait and notify() methods for first time and I tried in this way.
sample codes
public class Tester
{
static boolean closing == false;
static int n;
DateTime dt = new DateTime();
int getMin = dt.getMinuteOfDay(); //minute of the day
int tempMin = dt.getMinuteOfDay()+5;// minute of the day + 5 minutes
public static void setClosing(boolean b)
{
closing = b;
}
public static int getN()
{
return n;
}
class notifier extends Thread
{
public void run()
{
synchronized(this)
{
while(getMin == tempMin || closing == true)
{
notify();
}
}
}
}
public void starter() throws InterruptedException
{
notifier nn = new notifier();
while(n==1)
{
notify.start();
if(closing == false)
{
synchronized(notify)
{
nn.wait();
mailreader();
getMin = getMin+5;
tempMin = tempMin+5;
}
}
else
{
n=2;
}
}
}
}
main class
public class Tester2 extends WindowAdapter
{
public Tester2()
{
frame = new JFrame();
frame.addWindowListener(this);
frame.setVisible(true);
Tester t = new Tester();
t.starter();
}
#Override
public void windowClosing(WindowEvent e)
{
Tester.setClosing(true);
while(Tester.getN() != 2)
{
//wait
}
frame.dispose();
}
public static void main(String args[])
{
Tester2 t = new Tester2();
}
}
I am calling mailreader() method for every 5minutes to perform some task, but
when user closes the Jframe the closing is set to true from main class i want to come out of the while loop in notifier class.
All I am trying to do here is, when user closes the JFrame, i don't want the mailreader() to be stopped in middle and exit, instead i want the JFrame to wait until the method is finished and then close or if it is waiting mode(notifier class) i want to come to out of it and exit
If all you want to do is have something run periodically in a background thread, then get canceled in an orderly manner when the application closes, you don't need all this. Instead you can make a Runnable that loops, sleeping and doing its mail-reading, which quits when interrupted (the Runnable can control when it handles the interrupt so it's not in the middle of something). Once you start the thread, have the GUI keep a reference to it so it can call interrupt on it when closing.
Here's an example of how to cancel a thread using interrupt.

How to switch between two thread back and forth

I have two methods in two different classes, like this
public class ClassX implements Runnable {
public void methodAandB() {
for(int i=0;i<10;i++) {
System.out.println("This is A and B ");
}
}
#Override
public void run() {
methodAandB();
}
}
public class ClassY implements Runnable {
public void methodAorB() {
for(int i=0;i<10;i++) {
System.out.println("This is A or B");
}
}
#Override
public void run() {
methodAorB(a);
}
}
Thread t1 is calling methodAandB().
Thread t2 is calling methodAorB().
Can I switch between these two threads after each iteration of loop in methods?
I want to get output like this:
This is A and B
This is A or B
This is A and B
This is A or B
This is A and B
This is A or B
This is A and B
This is A or B
Best example of flip-flop between threads:
Given two int array (even and odd), 2 threads printing their numbers in natural order.
package com.rough;
public class ThreadsBehaviour {
static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
int a[] = {1,3,5,7,9};
int b[] = {2,4,6,8,10};
Thread odd = new Thread(new Looper(a, lock));
Thread even = new Thread(new Looper(b, lock));
odd.start();
even.start();
}
}
class Looper implements Runnable
{
int a[];
Object lock;
public Looper(int a[], Object lock)
{
this.a = a;
this.lock = lock;
}
#Override
public void run() {
for(int i = 0; i < a.length; i++)
{
synchronized(lock)
{
System.out.print(a[i]);
try
{
lock.notify();
if(i == (a.length - 1))
{
break;
}
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
You can achieve this simply by using the shared variables. I have implemented and verified the problem. code is below
class X
public class ClassX implements Runnable {
public void methodAandB() {
for(int i=0;i<10;i++) {
while(GlobalClass.isClassXdone)
{}
System.out.println("This is A and B ");
GlobalClass.isClassXdone = true;
GlobalClass.isClassYdone = false;
}}
#Override
public void run() {
methodAandB(); } }
ClassY
public class ClassY implements Runnable {
public void methodAorB() {
for(int i=0;i<10;i++) {
while(GlobalClass.isClassYdone)
{}
System.out.println("This is A or B ");
GlobalClass.isClassYdone = true;
GlobalClass.isClassXdone = false;}}
#Override
public void run() {
methodAorB();}}
Definition of the shared variable
public class GlobalClass {
public static boolean isClassXdone = false ;
public static boolean isClassYdone = false ;
}
You can just start your thread using t1.start and t2.start to get the desired output
Thread t1 = new Thread(new ClassX());
Thread t2 = new Thread(new ClassY());
t1.start();
t2.start();
This is probably more than needed to solve the problem, but, as it seems to be an introduction to concurrent programming exercise, it should be along the lines of what you'll encounter.
You should probably have a shared object that both your threads know, so that they may synchronize through it. Like so:
public class MyMutex {
private int whoGoes;
private int howMany;
public MyMutex(int first, int max) {
whoGoes = first;
howMany = max;
}
public synchronized int getWhoGoes() { return whoGoes; }
public synchronized void switchTurns() {
whoGoes = (whoGoes + 1) % howMany;
notifyAll();
}
public synchronized void waitForMyTurn(int id) throws
InterruptedException {
while (whoGoes != id) { wait(); }
}
}
Now, your classes should receive their respective identifier, and this shared object.
public class ClassX implements Runnable {
private final int MY_ID;
private final MyMutex MUTEX;
public ClassX(int id, MyMutex mutex) {
MY_ID = id;
MUTEX = mutex;
}
public void methodAandB() {
for(int i = 0; i < 10; i++) {
try {
MUTEX.waitForMyTurn(MY_ID);
System.out.println("This is A and B ");
MUTEX.switchTurns();
} catch (InterruptedException ex) {
// Handle it...
}
}
}
#Override
public void run() { methodAandB(); }
}
ClassY should do the same. Wait for its turn, do its action, and then yield the turn to the other.
I know it's a little late to answer this. But it's yesterday only I have come across this question. So I guess it's never too late.. ;)
Solution, as #afsantos mentioned is having a shared object between the two threads and implementing mutual exclusion on the shared object. The shared object could be alternatively locked by the two threads. Two possible implementations are as follows. This is actually more like an extension of #afsantos solution. His work is hereby acknowledged.
Solution 1:
Blueprint of the object that will be shared is as follows.
public class MutEx {
public int whoGoes, howMany;
public MutEx(int whoGoes, int howMany) {
this.whoGoes = whoGoes;
this.howMany = howMany;
}
public synchronized void switchTurns(){
this.whoGoes = (this.whoGoes + 1) % 2;
notifyAll();
}
public synchronized void waitForTurn(int id) throws InterruptedException{
while(this.whoGoes != id)
wait();
}
}
Then, you could implement the ClassX as follows.
public class ClassX implements Runnable {
private final int MY_ID;
private final MutEx MUT_EX;
public ThreadOne(int MY_ID, MutEx MUT_EX) {
this.MY_ID = MY_ID;
this.MUT_EX = MUT_EX;
}
#Override
public void run(){
this.doTheWork();
}
public void doTheWork(){
for(int i = 0; i < 10; i++){
try {
MUT_EX.waitForMyTurn(MY_ID);
System.out.println("This is A and B");
MUT_EX.switchTurns();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ClassY also will be the same, with whatever the differences you need to be there. Then, in the invocation (i.e. in the main method),
public static void main(String[] args) {
MutEx mutEx = new MutEx(0, 2);
Thread t1 = new Thread(new ClassX(0, mutEx);
Thread t2 = new Thread(new ClassY(1, mutEx));
t1.start();
t2.start();
}
Voila! You have two threads, alternating between each as you need.
Solution 2: Alternatively, you could implement the ClassX & ClassY as follows.
public class ClassX extends Thread{
Here, you are subclassing the java.lang.Thread to implement your requirement. For this to be invoked, change the main method as follows.
public static void main(String[] args) {
MutEx mutEx = new MutEx(0, 2);
ClassX t1 = new ClassX(0, mutEx);
ClassY t2 = new ClassY(1, mutEx);
t1.start();
t2.start();
}
Run this, and you have the same result.
If you don't need to use Thread try this code:
for (int i = 0; i < 20; i++) {
if (i % 2 == 0) {
methodAandB();
} else {
methodAorB();
}
}

Seems that Thread.start () does a notify ()

I've just found strange behavior in java threads.
Here is a code example:
class Job extends Thread {
private Integer number = 0;
public void run() {
for (int i = 1; i < 1000000; i++) {
number++;
}
}
public Integer getNumber() {
return number;
}
}
public class Test {
public static void main(String[] args)
throws InterruptedException {
Job thread = new Job();
thread.start();
synchronized (thread) {
thread.wait();
}
System.out.println(thread.getNumber());
}
}
Unexpectedly it'll print out the 999999.
Seems like there is notify() call at the end of start() method logic.
Any ideas?
Seems like there is notify() call at the end of start() method logic.
Yes, this is true. When a thread finishes it does a notify() which is how Thread.join() works. Here's a sample of the Java1.6 code for Thread.join():
public final synchronized void join(long millis) throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
...
That said, this may be implementation dependent and should not be relied on.

Categories

Resources