Using two threads and controlling one from the other in java? - java

Can someone please help me out.
I need to use two threads in a way that one thread will run permanently while(true) and will keep track of a positioning pointer (some random value coming in form a method). This thread has a logic, if the value equals something, it should start the new thread. And if the value does not equal it should stop the other thread.
Can someone give me some code snippet (block level) about how to realize this?

Create a class that implements Runnable. There you'll make a run() method.
Like:
public class StackOverflow implements Runnable{
private Thread t = null;
public void run(){
}
public void setAnotherThread(Thread t){
this.t = t;
}
}
On the main class, you'll create 2 instances of Thread based on the other class you created.
StackOverflow so1 = new StackOverflow();
StackOverflow so2 = new StackOverflow();
Thread t1 = new Thread(so1);
Thread t2 = new Thread(so2)
Then you set one thread in the other, so you can control it.
t1.setAnotherThread(so2);
t2.setAnotherThread(so1);
Then you do what you need to do.

Ok if I'm not mistaken, you want to have one class that could be run as a "Thread" or as a (lets call it) a "sub-Thread".
But how to do that with one run method? just declare a boolean variable that specifies whether the thread object is a sub-thread or a parent thread, and accordingly declare two constructors, one would create a parent thread and the other would create a sub thread, and to be able to stop the sub-thread declare another variable called stop that is default to false.
class ThreadExample extends Thread {
private boolean sub = false;
private ThreadExample subThread = null;
public boolean stop = false;
public ThreadExample() {
}
public ThreadExample(boolean sub) {
this.sub = sub;
}
public void run() {
if (sub) {
runSubMethod();
} else {
runParentMethod();
}
}
public void runParentMethod() {
boolean running = true;
while (running) {
if (getRandomValue() == some_other_value) {
if (getSubThread().isAlive()) {
continue;
}
getSubThread().start();
} else {
getSubThread().makeStop();
}
}
}
public void runSubMethod(){
while(true){
//do stuff
if (stop)
break;
}
}
public int getRandomValue() {
//your "Random Value"
return 0;
}
private ThreadExample getSubThread() {
if (subThread == null) {
subThread = new ThreadExample(true);
}
return subThread;
}
public void makeStop(){
stop = true;
}
}

Here is a simple idea how you can implement as many threads as you like in a class:
class MultipleThreads{
Runnable r1 = new Runnable() {
public void run() {
... code to be executed ...
}
};
//-----
Runnable r2 = new Runnable() {
public void run() {
... code to be executed ...
}
};
//--- continue as much you like
public static void main (String[] args){
Thread thr1 = new Thread(r1);
Thread thr2 = new Thread(r2);
thr1.start();
thr2.start();
}
}
Hope it helps!!
For communicating between the two threads, one simple solution is to set a boolean type volatile static variable, and have it set from one thread and put it in while(flag) condition in the other thread.
You can control the other thread using this method.
And if you have waiting processes or Thread.sleep() and you want to break the thread without having it to finish it, your interrupts by catching the exception.

Related

Print 1-1000 with two threads (even and odd) from the same class

So my task is this:
Instantiate two object of the same class
Provide a constructor argument, to designate a thread as even and another as odd .
Start both threads right one after other
Odd thread prints odd numbers from 0 to 1000
Even thread prints even numbers from 0 to 1000
However they should be in sync the prints should be 1 , 2 , 3 , 4 .....
One number on each line
However I can't seem to get the locks to release correctly. I've tried reading some of the similar problems on here but they all use multiple classes. What am I doing wrong?
Edit: My main class is doing this -
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
and my output is -
odd: 1
even: 2
...
public class NumberPrinter extends Thread {
private String name;
private int starterInt;
private boolean toggle;
public NumberPrinter(String name) {
super.setName(name);
this.name=name;
if(name.equals("odd")) {
starterInt=1;
toggle = true;
}
else if(name.equals("even")) {
starterInt=2;
toggle = false;
}
}
#Override
public synchronized void run() {
int localInt = starterInt;
boolean localToggle = toggle;
if(name.equals("odd")) {
while(localInt<1000) {
while(localToggle == false)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = false;
notify();
}
}
else {
while(localInt<1000) {
while(localToggle == true)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = true;
notify();
}
}
}
}
The key problem here is that the two threads have no way to coordinate with each other. When you have a local variable (localToggle in this case) nothing outside the method can observe or alter its value.
If you share one object with both threads, however, its state can change, and if used correctly, those state changes will be visible to both threads.
You will see examples where the shared object is an AtomicInteger, but when you use synchronized, wait() and notify(), you don't need the extra concurrency overhead built into the atomic wrappers.
Here's a simple outline:
class Main {
public static main(String... args) {
Main state = new Main();
new Thread(new Counter(state, false)).start();
new Thread(new Counter(state, true)).start();
}
int counter;
private static class Counter implements Runnable {
private final Main state;
private final boolean even;
Counter(Main state, boolean even) {
this.state = state;
this.even = even;
}
#Override
public void run() {
synchronized(state) {
/* Here, use wait and notify to read and update state.counter
* appropriately according to the "even" flag.
*/
}
}
}
}
I'm not clear whether using wait() and notify() yourself is part of the assignment, but an alternative to this outline would be to use something like a BlockingQueue to pass a token back and forth between the two threads. The (error-prone) condition monitoring would be built into the queue, cleaning up your code and making mistakes less likely.
I finally got it working in a way that meets the standards required by my assignment.
Thank you all for your input. I'll leave the answer here for anyone who might need it.
public class Demo {
public static void main(String[] args) {
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
System.out.println("Calling thread Done");
}
public class NumberPrinter extends Thread {
private int max = 1000;
static Object lock = new Object();
String name;
int remainder;
static int startNumber=1;
public NumberPrinter(String name) {
this.name = name;
if(name.equals("even")) {
remainder=0;
}else {
remainder=1;
}
}
#Override
public void run() {
while(startNumber<max) {
synchronized(lock) {
while(startNumber%2 !=remainder) {
try {
lock.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+": "+startNumber);
startNumber++;
lock.notifyAll();
}
}
}
}

Synchronized methods to avoid deadlock

I have two synchronized methods and I'm using the mediator design pattern.
I'm trying to avoid deadlocks, which is (from what I understand) for example when a thread has a lock on a variable res1 but needs a lock on variable res2. The other thread needs the lock for res1 but has the lock for res2 - resulting in a deadlock, right?
Assuming my understanding of deadlocks are correct, then my question is whether or not I have solved the issue of deadlock in this code?
I have two synchronized methods and two threads.
public class Producer extends Thread {
private Mediator med;
private int id;
private static int count = 1;
public Producer(Mediator m) {
med = m;
id = count++;
}
public void run() {
int num;
while(true) {
num = (int)(Math.random()*100);
med.storeMessage(num);
System.out.println("P-" + id + ": " + num);
}
}
}
public class Consumer extends Thread {
private Mediator med;
private int id;
private static int count = 1;
// laver kopling over til mediator
public Consumer(Mediator m) {
med = m;
id = count++;
}
public void run() {
int num;
while(true) {
num = med.retrieveMessage();
System.out.println("C" + id + ": " + num);
}
}
}
public class Mediator {
private int number;
private boolean slotFull = false;
public synchronized void storeMessage(int num) {
while(slotFull == true) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
slotFull = true;
number = num;
notifyAll();
}
public synchronized int retrieveMessage() {
while(slotFull == false) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
slotFull = false;
notifyAll();
return number;
}
}
public class MediatorTest {
public static void main(String[] args) {
Mediator mb = new Mediator();
new Producer(mb).start();
new Producer(mb).start();
new Producer(mb).start();
new Consumer(mb).start();
new Consumer(mb).start();
}
}
for example when a thread has a lock on a variable res1 but needs a lock on variable res2
What matters is not that there are two variables, what matters is that there must be two (or more) locks.
The names "res1" and "res2" are meant to suggest two resources each of which may have one or more variables, and each of which has its own lock. Here's where you get into trouble:
final Object lock1 = new Object();
final Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
// Call Thread.sleep(1000) here to simulate the thread losing its time slice.
synchronized(lock2) {
doSomethingThatRequiresBothLocks
}
}
}
public void method2() {
synchronized (lock2) {
// Do the same here 'cause you can't know which thread will get to run first.
synchronized(lock1) {
doSomethingElseThatRequiresBothLocks()
}
}
}
If thread A calls method1(), there is a very small chance that it could lose its time slice (i.e., turn to run) just after it successfully locks lock1, but before it locks lock2.
Then, while thread A is waiting its turn to run again, thread B calls method2(). Thread B will be able to lock lock2, but then it gets stuck because lock1 is locked by thread A. Furthermore, when thread A gets to run again, it will immediately be blocked when it tries to lock lock2 which is owned by thread B. Neither thread will ever be able to continue from that point.
In real code, it's never so obvious. When it happens in real-life, it usually is because of some unforseen interaction between code from two or more different modules that may not even be aware of each other, but which access the same common resources.
Your understanding of the basic deadlock problem is correct. With your second question about validity of your solution to the deadlock problem, you've only got 1 lock, so I'd say "yes" by default, since the deadlock you described isn't possible in this situation
I agree with what #ControlAltDel has said. And your understanding of a deadlock matches mine. Whereas there are a few different ways in which a deadlock can manifest itself, the way you describe -- inconsistently acquiring multiple monitors by involved threads (methods) causes deadlock.
Another way would be to (for example,) sleep while holding a lock. As you coded correctly, when the producer finds that slotFull = true, it waits, giving up the lock, so the other thread (consumer, which is sharing the same instance of Mediator with producer) can make progress potentially causing this thread also to make progress after it gets a notification. If you had chosen to call Thread.sleep() instead (naively hoping that someone will cause the sleep to end when the condition would be false), then it would cause a deadlock because this thread is sleeping, still holding the lock, denying access to the other thread.
Every object has one lock which restrict multiple threads to access same block of code or method when you use synchronized keyword.
Coming to your problem, it will not deadlock.
If you have two independent attribute in a class shared by multiple threads, you must synchronized the access to each variable, but there is no problem if one thread is accessing one of the attribute and another thread accessing the other at the same time.
class Cinema {
private long vacanciesCinema1; private long vacanciesCinema2;
private final Object controlCinema1, controlCinema2;
public Cinema() {
controlCinema1 = new Object();
controlCinema2 = new Object();
vacanciesCinema1 = 20;
vacanciesCinema2 = 20;
}
public boolean sellTickets1(int number) {
synchronized (controlCinema1) {
if (number < vacanciesCinema1) {
vacanciesCinema1 -= number;
return true;
} else {
return false;
}
}
}
public boolean sellTickets2(int number) {
synchronized (controlCinema2) {
if (number < vacanciesCinema2) {
vacanciesCinema2 -= number;
return true;
} else {
return false;
}
}
}
public boolean returnTickets1(int number) {
synchronized (controlCinema1) {
vacanciesCinema1 += number;
return true;
}
}
public boolean returnTickets2(int number) {
synchronized (controlCinema2) {
vacanciesCinema2 += number;
return true;
}
}
public long getVacanciesCinema1() {
return vacanciesCinema1;
}
public long getVacanciesCinema2() {
return vacanciesCinema2;
}
}
class TicketOffice1 implements Runnable {
private final Cinema cinema;
public TicketOffice1(Cinema cinema) {
this.cinema = cinema;
}
#Override
public void run() {
cinema.sellTickets1(3);
cinema.sellTickets1(2);
cinema.sellTickets2(2);
cinema.returnTickets1(3);
cinema.sellTickets1(5);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
}
}
public class CinemaMain {
public static void main(String[] args) {
Cinema cinema = new Cinema();
TicketOffice1 ticketOffice1 = new TicketOffice1(cinema);
Thread thread1 = new Thread(ticketOffice1, "TicketOffice1");
TicketOffice2 ticketOffice2 = new TicketOffice2(cinema);
Thread thread2 = new Thread(ticketOffice2, "TicketOffice2");
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Room 1 Vacancies: %d\n", cinema.getVacanciesCinema1());
System.out.printf("Room 2 Vacancies: %d\n", cinema.getVacanciesCinema2());
}
}

While loop and checking static variable

I have two threads and in one thread I set static variable and in another I check static variable via function like this
Test test= new Test();
while(!Temp.isVarSet()){
}
System.out.println("Variable set");
But this codes hangs - doesn't go to println statement. But the following code works
Test test= new Test();
while(!Temp.isVarSet()){
System.out.println("I am still here");
}
System.out.println("Variable set");
The Temp class
public class Temp {
private volatile static boolean varSet=false;
public synchronized static void setVarSet() {
Temp.varSet=true;
}
public synchronized static boolean isVarSet() {
return Temp.varSet;
}
}
Test class
public class Test{
public Test() {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Model model= new Model();
View view = new View();
Controller controller=new Controller(model, view);
Temp.setVarSet();
...
}
});
}
}
What can be reason? I set method isVarSet() synchronized but it didn't help.
EDIT
This code works too.
Test test = Test()
while(!Temp.isVarSet()){
Thread.sleep(100);
}
You didn't publish what happens in Temp and isVarSet but most probably you change a variable. This variable must be marked volatile.
If your class looks like this:
public class Temp {
private static boolean someFlag;
public static boolean isVarSet() {
return someFlag;
}
}
And your loop is the same as the example, the compiler thinks that there's no need to read the flag over and over again because the flag is not changed inside the loop and it optimizes to not read the flag over and over.
Marking someFlag as volatile:
private static volatile boolean someFlag;
Will force the runtime to check the flag on each iteration and not just assume that the value hasn't changed. In this case, it will work.
From Oracle docs about atomic access:
Atomic actions cannot be interleaved, so they can be used without fear
of thread interference. However, this does not eliminate all need to
synchronize atomic actions, because memory consistency errors are
still possible. Using volatile variables reduces the risk of memory
consistency errors, because any write to a volatile variable
establishes a happens-before relationship with subsequent reads of
that same variable. This means that changes to a volatile variable are
always visible to other threads. What's more, it also means that when
a thread reads a volatile variable, it sees not just the latest change
to the volatile, but also the side effects of the code that led up the
change.
Even after you made variable as volatile .
if you add SOP in while loop it is working
These two usecase gives me another thought. just try it.
Since your read and write methods are sync , in your while loop
while(!Temp.isVarSet()){
}
It is nothing doing other than calling the method, it may possible this sync method holds the lock on the Temp Object which does not allow other thread to modify the values (though sync setMethod) .
While add SOP inside the while , it is doing some work on IO and thus it is allowing some time slice to other thread get the lock of Temp and modify the same.
Could you please try remove Sync from read method , just for testing purpose and post your results.
public class Temp {
private volatile static boolean varSet=false;
public synchronized static void setVarSet() {
Temp.varSet=true;
}
public static boolean isVarSet() {
return Temp.varSet;
}
}
This works perfect for me:
public class ThreadTest {
public static void main(String[] args) throws Exception {
Thread t1 = new TheThread();
t1.start();
// wait
Thread.sleep(500);
System.out.println(Thread.currentThread().getId() + " will now setVarSet()");
Temp.setVarSet();
System.out.println(Thread.currentThread().getId() + " setVarSet() setted");
t1.join();
System.out.println(Thread.currentThread().getId() + " end programm");
}
private static class TheThread extends Thread {
#Override
public void run() {
System.out.println(Thread.currentThread().getId() + " enter run");
while (!Temp.isVarSet()) {
System.out.println(Thread.currentThread().getId() + " running");
try {
Thread.sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
// ignore
}
}
System.out.println(Thread.currentThread().getId() + " exit run");
}
}
private static class Temp {
private volatile static boolean varSet = false;
public static void setVarSet() {
Temp.varSet = true;
}
public static boolean isVarSet() {
return Temp.varSet;
}
}
}
Can you please post a complete example?
Its working as expected without hanging the program.
private volatile static boolean varSet = false;
public synchronized static void setVarSet() {
varSet = true;
}
public synchronized static boolean isVarSet() {
return varSet;
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
while (!TestDemo.isVarSet()) {
// System.out.println("I am still here");
}
System.out.println("Variable set");
}
});
t1.start();
Thread.sleep(1000); // put delay to give the chance to execute above thread
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
// Model model= new Model();
// View view = new View();
// Controller controller=new Controller(model, view);
setVarSet();
}
});
}

Java Thread Wait-Notify

I have 3 threads (A, B, C) that i just can't make them work how i want them to.
ALL these 3 threads share a reference to the same object - K.
What i'm trying to do, is to start all 3 up, then at some point in time when thread A arrives in a certain state, pause threads B and C, until A executes some method work() and when work finishes, resume B and C.
Now what i have in my code:
Thread A has reference to both B and C.
B and C have a method pause() { synchronized(K) { k.wait; }}
When A arrives in that certain state, i call FROM A's run() method: B.pause(), C.pause().
Now what i'm expecting is that Threads B and C will waiT until someone makes a: k.notifyAll(), BUT instead Thread A stops. Is this normal in java ?
Code:
class A implements Runnable {
private K k;
private B b;
private C c;
void run() {
while(something) {
//do something
b.pause();
c.pause();
// !!! here this thread will freeze and doSomething2 wont get executed.
// what i want is to pause B, C, doSomething2 to get executed and then resume B and C
//do something2
synchronized(k) {
k.notifyAll();
}
}
}
}
class B implements Runnable {
private K k;
void run() {
while(something) {
//dome something
}
}
}
public pause() {
synchronized(k) { k.wait();}
}
}
class C implements Runnable {
private K k;
void run() {
while(something) {
//dome something
}
}
}
public pause() {
synchronized(k) { k.wait();}
}
}
You can use a CylcicBarrier to implement this.
CyclicBarrier barrier = new CyclicBarrier();
public void run() {
new Thread(new A(barrier)).start();
new Thread(new B(barrier)).start();
barrier.await(); // Waits until all threads have called await()
// Do something
}
public void A implements Runnable {
private CyclicBarrier barrier;
public A(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
barrier.await();
// Do something.
}
}
public void B implements Runnable {
private CyclicBarrier barrier;
public B(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
barrier.await();
// Do something.
}
}
When you call B.pause(), it is executed in the local thread, not in the thread where you called run method of B.
There are some deprecated methods on the Thread class to do that but they are dangerous, see here:
http://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
Are you sure that you call b.pause() but declare B.sleep() ?
Would be nice to see threads construction/start code.
You know that you are using 3 diferent objects (monitors) A.k,B.k,C.k ?
So when B "paused" it synchronized on their own monitor (B.k) that should be free anyway.
Your threads do not "communicate" in any way.
Remove the calls to b.pause() and c.pause() from A.run() and call them from their own run methods.
Unless I am misunderstanding your homework assignment, what I think you need to do is learn how to interrupt a thread. B and C are interruptable threads that need to handle the interrupt in such a way that they will not resume until they have been told it is OK. It could look something like this:
while(true)
{
try
{
Thread.sleep(100);
System.out.println("Thread is working normally...");
}
catch(InterruptedException e)
{
System.out.println("Thread has been interrupted, will wait till A is done...");
try
{
synchronized(monitor)
{
monitor.wait();
}
}
catch(InterruptedException e2)
{
// whatever...
}
}
}
So object A running in its own thread will have references to two other threads. Object A will have access to a shared monitor object that the runnables in the two other threads also have access to (I called it monitor). When A interrupts the other threads their runnables will then call wait() on the monitor. When A is done it will call notifyAll() on the monitor. NOTE you should clear the interrupt flag in the other threads too, but I leave that to you to figure out - its easy :)
I don't normally help with homework in this detail, but I think you are using the wrong approach anyway, so I don't see the harm in helping you do something you almost certainly shouldn't be doing :)
class A implements Runnable {
private K k;
private B b;
private C c;
void run() {
while(something) {
//do something
b.pause();
c.pause();
// !!! here this thread will freeze and doSomething2 wont get executed.
// what i want is to pause B, C, doSomething2 to get executed and then resume B and C
//do something2
synchronized(k) {
k.notifyAll();
}
}
}
}
class B implements Runnable {
private K k;
volatile boolean isPaused = false;
void run() {
while(something) {
if (isPaused) {
synchronized(k) { k.wait();}
isPaused = false;
}
//dome something
}
}
public pause() {
isPaused = true;
}
}
class C implements Runnable {
private K k;
volatile boolean isPaused = false;
void run() {
while(something) {
if (isPaused) {
synchronized(k) {
k.wait();
}
isPaused = false;
}
//dome something
}
}
public pause() {
isPaused = true;
}
}
I'm guessing that what you really want to do though is unconditionally call wait in on k in B and C and then always call notifyAll in A

How can I implement a multi-threaded PID controller in Java?

I'm kinda new to Java, so haven't yet fully grasped the concept of multithreading.I would like to create a PIDController class that allows me to do this:
ControllerMethods methods = new ControllerMethods()
{
public long getError(long setpoint)
{
//get an input
}
public void setOutput(long value)
{
//do something
}
public void isComplete(long setpoint)
{
return getError() == 0;
}
};
PIDController motorPID = new PIDController(setpoint, kp, ki, kd, methods);
motorPID.run();
//runs the PID controller to completion (methods.isComplete() == true)
motorPID.run(false);
//starts the PID controller in a separate thread, allowing
//continual monitoring in the current thread
while(motorPID.isRunning())
{
//do something else
if(condition1)
motorPID.pause();
//pause the PID controller, preventing the integral from increasing
else if(condition2)
motorPID.stop();
}
I've worked out how to calculate the standard PID argorithms, but I can't work out how to provide the asynchronous functionality.
Can anybody tell me how I can achieve a similar API?
You already implemented a run() method for PIDController so you should also implement the Runnable interface:
class PIDController implements Runnable {
....
}
Now you can start your PIDController asynchonous, by calling:
pidControllerThread = new Thread( pidController );
pidControllerThread.start();
For synchronization (if needed) you should have a look at the sun concurrency guide.
By far, the best mechanism for attaching threads to anything is to separate the object which does the work from the object which is the thread. The Runnable interface can be attractive, because it allows people to pass the object to a Thread constructor or Executor, and run it. However, if you have lifecycle management requirements for your object which are out side of "running to completion", such as pausing, then you will find it more appropriate in most cases, to manage the Thread within your object so that you know which thread is running (yes you can set an instance object to Thread.currentThread() on entry to run, but...).
So, I think what you have is a good start. You need to add the use of some locking to help yourself manage pause() and other thread control.
public class PIDController {
private final Object myLock = new Object();
private final ControllerMethods ctrl;
private volatile Thread thread;
private volatile Runner runner;
private int pidInterval = 700;
private final double setPoint, kp, ki, kd;
public PIDController( double setPoint, double kp, double ki, double kd, ControllerMethods inst ) {
this.ctrl = inst;
this.setPoint = setPoint;
this.kp = kp;
this.ki = ki;
this.kd = kd;
}
public void pause() {
synchronized( myLock ) {
if( runner.paused ) {
throw new IllegalOperationException(this+": already paused");
}
runner.paused = true;
}
}
public void resume() {
synchronized( myLock ) {
if( !runner.paused ) {
throw new IllegalOperationException(this+": already resumed");
}
runner.paused = false;
}
}
public bool isRunning() {
return running;
}
public void start() {
if( thread != null ) {
throw new IllegalOperationException( this+": already running");
}
myThread = new Thread( runner = new Runner() );
myThread.start();
}
public void stop() {
if( runner == null ) {
throw new IllegalOperationException( this+": PID is not running");
}
runner.running = false;
if( runner.paused )
resume();
runner = null;
}
// It is important, anytime that you implement a stoppable Runnable, that
// you include the "running" flag as a member of an innner instance class like
// this so that when you ask this instance to stop, you can immediately restart
// another instance and not have the two threads observing the same "running" flag
private class Runner implements Runnable {
volatile bool running = false, bool paused;
public void run() {
running = true;
while( running ) {
// do this at the top of the loop so that a wake from
// pause will check running, before recomputing.
reComputePID();
// Use the double check idiom to
if( paused ) {
synchronized( myLock ) {
while( paused ) {
myLock.wait();
}
}
}
Thread.sleep( pidInterval );
}
}
}
public void reComputePID() {
...
}
}

Categories

Resources