Does this non-standard Java synchronization pattern work? - java

Let's say I have two threads running like this:
Thread A which performs computation while updating pixels of a shared image
Thread B periodically reads the image and copies it to the screen
Thread A performs work quickly, say 1 million updates per second, so I suspect it would be a bad idea to lock and unlock on a lock/mutex/monitor that often. But if there is no lock and no way of establishing a happens-before relation from thread A to thread B, then by the Java memory model (JMM spec) thread B is not guaranteed at all to see any of A's updates to the image.
So I was thinking that the minimum solution is for threads A and B to both synchronize periodically on the same shared lock, but not actually perform any work while inside the synchronized block - this is what makes the pattern non-standard and dubious. To illustrate in half-real half-pseudo code:
class ComputationCanvas extends java.awt.Canvas {
private Object lock = new Object();
private int[] pixels = new int[1000000];
public ComputationCanvas() {
new Thread(this::runThreadA).start();
new Thread(this::runThreadB).start();
}
private void runThreadA() {
while (true) {
for (1000 steps) {
update pixels directly
without synchornization
}
synchronized(lock) {} // Blank
}
}
private void runThreadB() {
while (true) {
Thread.sleep(100);
synchronized(lock) {} // Blank
this.repaint();
}
}
#Override
public void paint(Graphics g) {
g.drawImage(pixels, 0, 0);
}
}
Does adding empty synchronization blocks in this way correctly achieve the effect of transferring data from thread A to thread B? Or is there some other solution I failed to imagine?

Yes it works. But it works horribly.
Happens before only works when the release of the writer happens before the acquire of the reader. Your implementation assumes that whatever you're writing will complete before the subsequent reading/updating from ThreadB. Causing your data to be flushed all the time by synchronized will cause performance problems, although to what extent I cannot say for sure. Sure, you've made your synchronization finer grained, have you tested it yet?
A better solution might use a singleton/transfer SPSC (single producer/single consumer) queue to store the current snapshot of the writing thread and use that whenever you update.
int[] data = ...
Queue<int[]> queue = new ...
// Thread A
while (true) {
for (1000 iterations or so) {
...
}
queue.add(data);
}
// Thread B
while (true) {
int[] snapshot = queue.take();
this.repaint();
}
The advantage of this is that you don't need to busywait, you can just wait for the queue to block or until the next write. You can skip writes that you don't have time to update. You don't need to depend on the arbitrary thread scheduler to plan data flushes for you.
Remember that thread-safe data structures are great for passing data between threads.
Edit: oops, forgot to say that depending on how your updates go, you might want to use an array copy to prevent your data from being garbled from random writes that aren't cached.

Related

About Thread's wait()/ notify

I was trying to write an example on how to use wait() and notify(), but seems that the wait() can't be notified
public class Transfer {
private int[] data;
private volatile int ptr;
private final Object lock = new Object();
public Transfer(int[] data) {
this.data = data;
this.ptr = 0;
}
public void send() {
while (ptr < data.length) {
synchronized (lock) {
try {
System.out.println("-----wait");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
ptr++;
}
}
}
public void receive() {
while (ptr < data.length) {
synchronized (lock) {
System.out.println("current is " + data[ptr]);
System.out.println("-----notify");
lock.notifyAll();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
////in main()
int[] data = new int[] { 111, 222, 333, 444, 555, 666, 777, 888, 999, 000 };
Transfer tf = new Transfer(data);
Thread t1 = new Thread(() -> {
tf.receive();
});
Thread t2 = new Thread(() -> {
tf.send();
});
t2.start();
t1.start();
but the result is :
-----wait
current is 111
-----notify
current is 111
-----notify
[endless repeat]
this is not what I expected, it should be :
current is 111
current is 222...
The problem with your code specifically is that you are keeping your locks way too long.
I'll first explain how wait/notify works, which is intricately connected with the concept of the monitor (synchronized), then how to do it right, and then as an encore, that you probably don't want to use this at all, it's too low level.
How does 'synchronized' work
When you write synchronized(x) you acquire the monitor - this operation can do one of three things. In all cases, x is a reference, so the reference is followed, it's about the object you find by following it.
If the reference is null, this immediately throws NPE.
If the object x points at has no current monitor, this thread becomes the monitor, the monitor count becomes 1, and code continues.
If the object x points at has a monitor but it is this thread, then the monitor count is incremented and code continues.
If the object x points at has a monitor but it is another thread, the thread will block until the monitor becomes available. Once it is available, some unfair dice show up, are rolled, and determine which of all threads 'fighting' to acquire the monitor will acquire it. Unfair in the sense that there are no guarantees made and the JVM is free to use any algorithm it wants to decide who 'wins'. If your code depends on fairness or some set order, your code is broken.
Upon reaching the } of the synchronized block, the monitor count is decremented. If it hits 0, the monitor is released (and the fight as per #4 starts, if other threads are waiting). In other words, locks are 're-entrant' in java. A thread can write synchronized(a){synchronized(a){}} and won't deadlock with itself.
Yes, this establishes comes-before stuff as per the Java Memory Model: Any fights arbitrated by a synchronized block will also ensure any writes by things that clearly came before (as established by who wins the fight) are observable by anything that clearly came after.
A method marked as 'synchronized' is effectively equivalent to wrapping the code in synchronized(this) for instance methods, and synchronized(MyClass.class) for static methods.
Monitors are not released and cannot be changed in java code* except via that } mechanism; (there is no public Thread getMonitor() {..} in j.l.Object or anywhere else) - in particular if the thread blocks for any other reason, including Thread.sleep, the monitor status does not change - your thread continues to hold on to it and thus stops all other threads from acquiring it. With one exception:
So how does wait/notify factor into this?
to wait/notify on x you MUST hold the monitor. this: x.notify();, unless it is wrapped in a synchronized(x) block, does not work.
When you wait(), the monitor is released, and the monitor count is remembered. a call to wait() requires 2 things to happen before it can continue: The 'wait' needs to be cancelled, either via a timeout, or an interrupt, or via a notify(All), and the thread needs to acquire that monitor again. If done normally (via a notify), by definition this is a fight, as whomever called notify neccessarily is still holding that monitor.
This then explains why your code does not work - your 'receiver' snippet holds on to the monitor while it sleeps. Take the sleep outside of the synchronized.
How do you use this, generally
The best way to use wait/notifyAll is not to make too many assumptions about the 'flow' of locking and unlocking. Only after acquiring the monitor, check some status. If the status is such that you need to wait for something to happen, then and only then start the wait() cycle. The thread that will cause that event to happen will first have to acquire the monitor and only then set steps to start the event. If this is not possible, that's okay - put in a failsafe, make the code that wait()s use a timeout (wait(500L) for example), so that if things fail, the while loop will fix the problem. Furthermore, there really is no good reason to ever use notify so forget that exists. notify makes no guarantees about what it'll unlock, and given that all threads that use wait ought to be checking the condition they were waiting for regardless of the behaviour of wait, notifyAll is always the right call to make.
So, it looks like this... let's say we're waiting for some file to exist.
// waiting side:
Path target = Paths.get("/file-i-am-waiting-for.txt");
synchronized (lock) {
while (!Files.isRegularFile(target)) {
try {
lock.wait(1000L);
} catch (InterruptedException e) {
// this exception occurs ONLY
// if some code explicitly called Thread.interrupt()
// on this thread. You therefore know what it means.
// usually, logging interruptedex is wrong!
// let's say here you intended it to mean: just exit
// and do nothing.
// to be clear: Interrupted does not mean:
// 'someone pressed CTRL+C' or 'the system is about to shutdown'.
return;
}
}
performOperation(target);
}
And on the 'file creation' side:
Path tgt = Paths.get("/file-i-am-waiting-for.txt");
Path create = tgt.getParent().resolve(tgt.getFileName() + ".create");
fillWithContent(create);
synchronized (lock) {
Files.move(create, tgt, StandardOpenOption.ATOMIC_MOVE);
lock.notifyAll();
}
The 'sending' (notifying) side is very simple, and note how we're using the file system to ensure that if the tgt file exists at all, it's fully formed and not a half-baked product. The receiving side uses a while loop: the notifying is itself NOT the signal to continue; it is merely the signal to re-check for the existence of this file. This is almost always how to do this stuff. Note also how all code involved with that file is always only doing things when they hold the lock, thus ensuring no clashes on that part.
But.. this is fairly low level stuff
The java.util.concurrent package has superior tooling for this stuff; for example, you may want a latch here, or a ReadWriteLock. They tend to outperform you, too.
But even juc is low level. Generally threading works best if the comm channel used between threads is inherently designed around concurrency. DBs (with a proper transaction level, such as SERIALIZABLE), or message buses like rabbitmq are such things. Why do you think script kiddies fresh off of an 8 hour course on PHP can manage to smash a website together that actually does at least hold up, thread-wise, even if it's littered with security issues? Because PHP enforces a model where all comms run through a DB because PHP is incapable of anything else in its basic deployment. As silly as these handcuffs may sound, the principle is solid, and can be applied just as easily from java.
*) sun.misc.Unsafe can do it, but it's called Unsafe for a reason.
Some closing best practices
Locks should be private; this is a rule broken by most examples and a lot of java code. You've done it right: if you're going to use synchronized, it should probably be on lock, which is private final Object lock = new Object();. Make it new Object[0] if you need it to be serializable, which arrays are, and Objects aren't.
if ever there is code in your system that does: synchronized(a) { synchronized (b) { ... }} and also code that odes: synchronized(b) { synchronized (a) { ... }} you're going to run into a deadlock at some point (each have acquired the first lock and are waiting for the second. They will be waiting forever. Be REAL careful when acquiring more than one monitor, and if you must, put in a ton of effort to ensure that you always acquire them in the same order to avoid deadlocks. Fortunately, jstack and such (tools to introspect running VMs) can tell you about deadlocks. The JVM itself, unfortunately, will just freeze in its tracks, dead as a doornail, if you deadlock it.
class Transfer {
private int[] data;
private volatile int ptr;
private final Object lock = new Object();
public Transfer(int[] data) {
this.data = data;
this.ptr = 0;
}
public void send() {
while (ptr < data.length) {
synchronized (lock) {
try {
System.out.println("-----wait");
lock.notifyAll();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
ptr++;
}
}
}
public void receive() {
while (ptr < data.length) {
synchronized (lock) {
System.out.println("current is " + data[ptr]);
System.out.println("-----notify");
try {
lock.notifyAll();
lock.wait();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
"Thread.sleep" does not release the lock. So you need "lock.wait" to release the lock and let other thread proceed. Then after "send" increment the pointer, it should also notify so that other thread who is stuck at receive can now proceed.

Java Multithreading large arrays access

My main class, generates multiple threads based on some rules. (20-40 threads live for long time).
Each thread create several threads (short time ) --> I am using executer for this one.
I need to work on Multi dimension arrays in the short time threads --> I wrote it like it is in the code below --> but I think that it is not efficient since I pass it so many times to so many threads / tasks --. I tried to access it directly from the threads (by declaring it as public --> no success) --> will be happy to get comments / advices on how to improve it.
I also look at next step to return a 1 dimension array as a result (which might be better just to update it at the Assetfactory class ) --> and I am not sure how to.
please see the code below.
thanks
Paz
import java.util.concurrent.*;
import java.util.logging.Level;
public class AssetFactory implements Runnable{
private volatile boolean stop = false;
private volatile String feed ;
private double[][][] PeriodRates= new double[10][500][4];
private String TimeStr,Bid,periodicalRateIndicator;
private final BlockingQueue<String> workQueue;
ExecutorService IndicatorPool = Executors.newCachedThreadPool();
public AssetFactory(BlockingQueue<String> workQueue) {
this.workQueue = workQueue;
}
#Override
public void run(){
while (!stop) {
try{
feed = workQueue.take();
periodicalRateIndicator = CheckPeriod(TimeStr, Bid) ;
if (periodicalRateIndicator.length() >0) {
IndicatorPool.submit(new CalcMvg(periodicalRateIndicator,PeriodRates));
}
}
if ("Stop".equals(feed)) {
stop = true ;
}
} // try
catch (InterruptedException ex) {
logger.log(Level.SEVERE, null, ex);
stop = true;
}
} // while
} // run
Here is the CalcMVG class
public class CalcMvg implements Runnable {
private double [][][] PeriodRates = new double[10][500][4];
public CalcMvg(String Periods, double[][][] PeriodRates) {
System.out.println(Periods);
this.PeriodRates = PeriodRates ;
}
#Override
public void run(){
try{
// do some work with the data of PeriodRates array e.g. print it (no changes to array
System.out.println(PeriodRates[1][1][1]);
}
catch (Exception ex){
System.out.println(Thread.currentThread().getName() + ex.getMessage());
logger.log(Level.SEVERE, null, ex);
}
}//run
} // mvg class
There are several things going on here which seem to be wrong, but it is hard to give a good answer with the limited amount of code presented.
First the actual coding issues:
There is no need to define a variable as volatile if only one thread ever accesses it (stop, feed)
You should declare variables that are only used in a local context (run method) locally in that function and not globally for the whole instance (almost all variables). This allows the JIT to do various optimizations.
The InterruptedException should terminate the thread. Because it is thrown as a request to terminate the thread's work.
In your code example the workQueue doesn't seem to do anything but to put the threads to sleep or stop them. Why doesn't it just immediately feed the actual worker-threads with the required workload?
And then the code structure issues:
You use threads to feed threads with work. This is inefficient, as you only have a limited amount of cores that can actually do the work. As the execution order of threads is undefined, it is likely that the IndicatorPool is either mostly idle or overfilling with tasks that have not yet been done.
If you have a finite set of work to be done, the ExecutorCompletionService might be helpful for your task.
I think you will gain the best speed increase by redesigning the code structure. Imagine the following (assuming that I understood your question correctly):
There is a blocking queue of tasks that is fed by some data source (e.g. file-stream, network).
A set of worker-threads equal to the amount of cores is waiting on that data source for input, which is then processed and put into a completion queue.
A specific data set is the "terminator" for your work (e.g. "null"). If a thread encounters this terminator, it finishes it's loop and shuts down.
Now the following holds true for this construct:
Case 1: The data source is the bottle-neck. It cannot be speed-up by using multiple threads, as your harddisk/network won't work faster if you ask more often.
Case 2: The processing power on your machine is the bottle neck, as you cannot process more data than the worker threads/cores on your machine can handle.
In both cases the conclusion is, that the worker threads need to be the ones that seek for new data as soon as they are ready to process it. As either they need to be put on hold or they need to throttle the incoming data. This will ensure maximum throughput.
If all worker threads have terminated, the work is done. This can be i.E. tracked through the use of a CyclicBarrier or Phaser class.
Pseudo-code for the worker threads:
public void run() {
DataType e;
try {
while ((e = dataSource.next()) != null) {
process(e);
}
barrier.await();
} catch (InterruptedException ex) {
}
}
I hope this is helpful on your case.
Passing the array as an argument to the constructor is a reasonable approach, although unless you intend to copy the array it isn't necessary to initialize PeriodRates with a large array. It seems wasteful to allocate a large block of memory and then reassign its only reference straight away in the constructor. I would initialize it like this:
private final double [][][] PeriodRates;
public CalcMvg(String Periods, double[][][] PeriodRates) {
System.out.println(Periods);
this.PeriodRates = PeriodRates;
}
The other option is to define CalcMvg as an inner class of AssetFactory and declare PeriodRate as final. This would allow instances of CalcMvg to access PeriodRate in the outer instance of AssetFactory.
Returning the result is more difficult since it involves publishing the result across threads. One way to do this is to use synchronized methods:
private double[] result = null;
private synchronized void setResult(double[] result) {
this.result = result;
}
public synchronized double[] getResult() {
if (result == null) {
throw new RuntimeException("Result has not been initialized for this instance: " + this);
}
return result;
}
There are more advanced multi-threading concepts available in the Java libraries, e.g. Future, that might be appropriate in this case.
Regarding your concerns about the number of threads, allowing a library class to manage the allocation of work to a thread pool might solve this concern. Something like an Executor might help with this.

Java - How To Synchronize 2 Threads On 1 List?

How can I synchronize 2 threads to handle data in a list ?
thread A is adding / changing items in a list (writing to the list)
thread B is displaying the items (only reading the list)
I would like to "notify" thread B when it can display the list. In the time of reading the list it must not be changed by thread A. When thread B is done reading, thread A can start changing the list again.
My guesses go to
synchronized(obj)
list.wait() + list.notify()
Threads aren't invoking each other. They run concurrent all the time.
You could put all changes in Runnables and put them in a queue that Thread A executes in order. After each job, A must generate a snapshot of the modified list and submit it to Thread B. You could use Executors for that.
General concept (as I see it in your case) would be as follows.
1) Create an instance of List that you're planning to work with.
2) Write 2 classes corresponding to your thread A and thread B that both implement Runnable and take List as their constructor parameter.
3) Synchronize these 2 classes on list instance:
// method in class that adds
public void add() {
synchronized(list) {
// perform addition ...
list.notify();
}
}
// method in class that reads
public void read() throws InterruptedException {
synchronized(list) {
while (list.isEmpty())
list.wait();
// process data ...
}
}
4) Create 2 threads with argumens corresponding to instances of these 2 classes and start them.
Reader and writer locks are your friends here.
•thread A is adding / changing items in a list (writing to the list)
... so it can use the write lock ...
•thread B is displaying the items (only reading the list)
... so it can use the read lock.
Let's assume that you're using something straight forward for your wait/notify (for example, the built-in Object methods) to block the read and display thread. At that point, your code looks something like this:
/** This is the read/write lock that both threads can see */
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
/** This method is called by thread A (the writer / modifier) */
public void add() {
try {
// Only one writer at a time allowed
lock.writeLock().lock();
// Insert code here: Add to the list
} finally {
// Unlock in the finally block to ensure that lock is released
lock.writeLock().unlock();
}
// Notify anyone who's waiting for data
list.notify();
}
/** This method is called by thread B (the reader / displayer) */
public void read() throws InterruptedException {
try {
// As many readers as you like at a time
lock.readLock().lock();
// Insert code here: read from the list
} finally {
// Unlock in the finally block to ensure that lock is released
lock.readLock().unlock();
}
// Wait for new data
list.wait();
}
To make things even more convenient, you can get rid of the notify/wait messaging by using a blocking data structure: e.g., one of the BlockingQueues. In that case, you don't write any notification at all. The reader blocks waiting for new data. When the writer adds data to the queue, the reader unblocks, drains the new data to process, does its thing and then blocks again.
I tried concurrency packages suggested here or here and it works well. The threads lock each other out:
final Lock lock = new ReentrantLock(true);
// thread A
lock.lock();
// write to list
lock.unlock();
// thread B
lock.lock();
// read from list
lock.unlock();
Not sure if they can execute precisely one after another and I didn't get the notify feature. But that doesn't hurt my application.

How to correctly use synchronized?

This piece of code:
synchronized (mList) {
if (mList.size() != 0) {
int s = mList.size() - 1;
for (int i = s; i > 0; i -= OFFSET) {
mList.get(i).doDraw(canv);
}
getHead().drawHead(canv);
}
}
Randomly throws AIOOBEs. From what I've read, the synchronized should prevent that, so what am I doing wrong?
Edits:
AIOOBE = Array Index Out Of Bounds Exception
The code's incomplete, cut down to what is needed. But to make you happy, OFFSET is 4, and just imagine that there is a for-loop adding a bit of data at the beginning. And a second thread reading and / or modifying the list.
Edit 2:
I've noticed it happens when the list is being drawn and the current game ends. The draw-thread hasn't drawn all elements when the list is emptied. Is there a way of telling the game to wait with emtying the list untill it's empty?
Edit 3:
I've just noticed that I'm not sure if this is a multi-threading problem. Seems I only have 2 threads, one for calculating and drawing and one for user input.. Gonna have to look into this a bit more than I thought.
What you're doing looks right... but that's all:
It doesn't matter on what object you synchronize, it needn't be the list itself.
What does matter is if all threads always synchronize on the same object, when accessing a shared resource.
Any access to SWING (or another graphic library) must happen in the AWT-Thread.
To your edit:
I've noticed it happens when the list is being drawn and the current game ends. The draw-thread hasn't drawn all elements when the list is emptied. Is there a way of telling the game to wait with emtying the list untill it's empty?
I think you mean "...wait with emptying the list until the drawing has completed." Just synchronize the code doing it on the same lock (i.e., the list itself in your case).
Again: Any access to a shared resource must be protected somehow. It seems like you're using synchronized just here and not where you're emptying the list.
The safe solution is to only allow one thread to create objects, add and remove them from a List after the game has started.
I had problems myself with random AIOOBEs erros and no synchornize could solve it properly plus it was slowing down the response of the user.
My solution, which is now stable and fast (never had an AIOOBEs since) is to make UI thread inform the game thread to create or manipulate an object by setting a flag and coordinates of the touch into the persistent variables.
Since the game thread loops about 60 times per second this proved to be sufficent to pick up the message from the UI thread and do something.
This is a very simple solution and it works great!
My suggestion is to use a BlockingQueue and I think you are looking for this solution also. How you can do it? It is already shown with an example in the javadoc :)
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
The beneficial things for you are, you need not to worry about synchronizing your mList. BlockingQueue offers 10 special method. You can check it in the doc. Few from javadoc:
BlockingQueue methods come in four forms, with different ways of handling operations that cannot be satisfied immediately, but may be satisfied at some point in the future: one throws an exception, the second returns a special value (either null or false, depending on the operation), the third blocks the current thread indefinitely until the operation can succeed, and the fourth blocks for only a given maximum time limit before giving up.
To be in safe side: I am not experienced with android. So not certain whether all java packages are allowed in android. But at least it should be :-S, I wish.
You are getting Index out of Bounds Exception because there are 2 threads that operate on the list and are doing it wrongly.
You should have been synchronizing at another level, in such a way that no other thread can iterate through the list while other thread is modifying it! Only on thread at a time should 'work on' the list.
I guess you have the following situation:
//piece of code that adds some item in the list
synchronized(mList){
mList.add(1, drawableElem);
...
}
and
//code that iterates you list(your code simplified)
synchronized (mList) {
if (mList.size() != 0) {
int s = mList.size() - 1;
for (int i = s; i > 0; i -= OFFSET) {
mList.get(i).doDraw(canv);
}
getHead().drawHead(canv);
}
}
Individually the pieces of code look fine. They seam thread-safe. But 2 individual thread-safe pieces of code might not be thread safe at a higher level!
It's just you would have done the following:
Vector v = new Vector();
if(v.length() == 0){ v.length() itself is thread safe!
v.add("elem"); v.add() itself is also thread safe individually!
}
BUT the compound operation is NOT!
Regards,
Tiberiu

Thread that can restart based on a condition

The basic idea is that I have a native function I want to call in a background thread with a user selected value and the thread cannot be interrupted when started. If the user decides to change the value used to perform the task while the thread is running (they can do this from a GUI), the thread should finish its task with the previous value and then restart with the new value. When the task is done and the value hasn't changed, the thread should end and call a callback function.
This is what my current code looks like for the thread starting part:
volatile int taskValue;
volatile boolean taskShouldRestart;
void setTaskValue(int value)
{
taskValue = value;
synchronized (threadShouldRestart)
{
if task thread is already running
threadShouldRestart = true
else
{
threadShouldRestart = false
create and start new thread
}
}
}
And the actual work thread looks like this:
while (true)
{
nativeFunctionCall(taskValue);
synchronized (threadShouldRestart)
{
if (!threadShouldRestart)
{
invokeTaskCompletedCallbackFunction();
return;
}
}
}
I'm locking on the "threadShouldRestart" part because e.g. I don't want this changing to true just as the thread decides it's done which means the thread wouldn't restart when it was meant to.
Are there any cleaner ways to do this or Java utility classes I could be using?
You could design your run() method as follows:
public void run() {
int currentTaskValue;
do {
currentTaskValue = taskValue;
// perform the work...
} while (currentTaskValue != taskValue);
}
I think the volatile declaration on taskValue is enough for this, since reads and writes of primitives no larger than 32 bits are atomic.
Have you considered a ThreadPoolExecutor? It seems to lend itself well to your problem as you mentioned you have no need to restart or stop a thread which has already started.
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html
A user could submit as many tasks as they like to a task queue, tasks will be processed concurrently by some number of worker threads you define in the ThreadPoolExecutor constructor.

Categories

Resources