I am currently learning basics of Threads in Java and I am trying to write a program simulating a 2x200 Relay race with 2 teams. I would like to have 2 teams (represented by a ThreadGroup each) and each team has 2 members, each of which must run for 200 m. Here running is just simulated by looping in a for loop and printing. I am not able to find a straight forward way of running threads in a Threadgroup in serially
Here is how the worker looks like
public class RelayRunner implements Runnable {
#Override
public void run() {
for (int i = 1; i <= 200; i++) {
String name = Thread.currentThread().getName();
if (i % 50 == 0) {
System.out.format("%s ran %d m \n", name, i);
}
}
}
}
Here is how the main program looks like
public class RelayRunnerMatch {
public static void main(String[] args) {
RelayRunner relayRunner = new RelayRunner();
ThreadGroup usa = new ThreadGroup("USA");
ThreadGroup germany = new ThreadGroup("GERMANY");
Thread usa1 = new Thread(usa, relayRunner, "usa1");
Thread germany1 = new Thread(germany, relayRunner, "germany1");
Thread usa2 = new Thread(usa, relayRunner, "usa2");
Thread germany2 = new Thread(germany, relayRunner, "germany2");
usa1.start();
germany1.start();
/* Now I would like to start the second thread in a group only if the first
thread in the same group has finished like in a real relay race. How??
*/
//usa1.join(); germany1.join();
//usa2.start(); germany2.start() --> Not good, usa2 must start immediately when usa1 has finished
}
}
I am not able to see how the join() may be of any help here as it will wait for both threads to finish before the second set of runners can start their run. Also I realize that activeCount() is just an estimate, so I am not sure of using that either.
Is there a solution possible without resorting to services in new Concurrent API(as I haven't reached that further)?
public class Player1 implements Runnable{
private final CountDownLatch countDownLatch;
private final String s;
public Player1(CountDownLatch c, String s){
this.countDownLatch=c;
this.s=s;
}
#Override
public void run() {
for(int i=0;i<200;i++){
System.out.println(s+":"+i);
}
countDownLatch.countDown();
}
}
public class Player2 implements Runnable{
private final CountDownLatch countDownLatch;
private final String s;
public Player2(CountDownLatch c, String s){
this.countDownLatch = c;
this.s=s;
}
#Override
public void run() {
try {
countDownLatch.await();
} catch (InterruptedException ex) {
Logger.getLogger(Player2.class.getName()).log(Level.SEVERE, null, ex);
}
for(int i=0;i<200;i++){
System.out.println(s+":"+i);
}
}
}
Driver program:
public static void main(String[] args){
Thread[] grp1 = new Thread[2];
Thread[] grp2 = new Thread[2];
CountDownLatch c1 = new CountDownLatch(1);
CountDownLatch c2 = new CountDownLatch(1);
grp1[0]=new Thread(new Player1(c1, "grp1:player1"));
grp1[1]=new Thread(new Player2(c2, "grp1:player2"));
grp2[0]=new Thread(new Player1(c2, "grp2:player1"));
grp2[1]=new Thread(new Player2(c2, "grp2:player2"));
grp1[0].start();
grp2[0].start();
grp1[1].start();
grp2[1].start();
}
You could create two baton-objects and synchronize on the respective baton so the second thread would have to wait until the first one releases the baton - or use some locks from java.util.concurrent.locks-package to achieve the same. But your relay-members will compete in who gets the baton first or next and you can't define some real order.
But as Jarrod said: when you have several tasks that have to be executed sequentially you better execute them on the same thread: have some runner-objects and add them to a queue on the respective relay-thread that calls their run-method one after the other.
Related
I'm new to threads. I wanted to get two threads to increment an integer to a certain value. because int type is immutable, I switched to atomic integer. I also tried to wrap an int to a class and that didn't work either. I also tried static/volatile int and that didn't work. I also tried to use fairness policy. The main issue is that "counterObj" is not incremented correctly and is still set to 0 even though it is injected to both threads.
My expected running behavior:
thread value
thread 0 0
thread 1 1
thread 0 2
...
What I wrote so far:
import java.util.concurrent.atomic.AtomicInteger;
public class Application {
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void launch() throws InterruptedException {
int increments = 100;
AtomicInteger counterObj = new AtomicInteger(0);
CounterThread th1 = new CounterThread("1", counterObj, increments);
CounterThread th2 = new CounterThread("2", counterObj, increments);
th1.start();
th2.start();
System.out.println(counterObj.get());
}
}
and
import java.util.concurrent.atomic.AtomicInteger;
public class CounterThread implements Runnable {
private final String threadID;
private AtomicInteger counterObj;
private int bound;
public CounterThread(String threadID, AtomicInteger counter, int bound) {
this.threadID = threadID;
this.counterObj = counter;
this.bound = bound;
}
#Override
public synchronized void run() {
while (counterObj.get() < bound) {
synchronized (this) {
counterObj.incrementAndGet();
}
}
System.out.println("Thread " + threadID + " finished");
}
public void start() throws InterruptedException {
Thread thread = new Thread(this, threadID);
thread.join();
thread.start();
}
}
Cheers!
I think your program is exiting before your threads get a chance to do anything (probably due to the ordering of your starts and joins. I would move your thread starting logic into your main(or launch) method. Something like the following.
Thread thread1 = new Thread(new MyCounterRunnable("1", counterObj, increments));
Thread thread2 = new Thread(new MyCounterRunnable("2", counterObj, increments));
Then, in your main, you need to call join after starting the threads...as follows:
thread1.start(); // starts first thread.
thread2.start(); // starts second thread.
thread1.join(); // don't let main exit until thread 1 is done.
thread2.join(); // don't let main exit until thread 2 is done.
What you really are wanting is for only one thread to increment an int at a time.
The int variable is the resource you want in the synchronized block, so the different threads can increment it one at a time.
This can be done using syncrhonize alone.
Disclaimer: I didn't run the code so it could have some typo or Exceptions to be removed from the Application class.
public class Application {
private int theVar = 0;
private int increments = 100;
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized addOne(){
this.theVar++;
}
private void launch() throws InterruptedException {
Runnable counter1 = new Counter(this, increments), counter2 = new Counter(this, increments);
Thread t1 = new Thread(counter1);
Thread t2 = new Thread(counter2);
t1.start();
t2.start();
}
}
A counter class
public class Counter implements Runnable{
private Application app;
int rounds = -1;
public Counter(Application app, rounds){
this.app = app;
this.rounds = rounds;
}
public void run(){
while(int i=0; i<rounds; i++){
this.app.addOne();
}
}
}
AtomicInteger takes care of atomicity itself, so you shouldn't need to use synchronized -- but only if you play by the rules, and do your atomic operations in one call.
You're failing to do this, because you call counterObj.get() then depending on the result counterObj.incrementAndGet(). You need to avoid this because you want the check and the update to be part of the same atomic chunk of work.
You can get close with:
while(counterObj.incrementAndGet() < bound) {} ;
But this will always increment at least once, which may be once too many.
Slightly more involved:
IntUnaryOperator incrementWithLimit = x ->
( x < bound ? x + 1 : x );
while(counterObj.updateAndGet(incrementWithLimit) < bound) {};
That is, we've created a function that increments a number only if it's lower than bound, and we tell AtomicInteger to apply that.
There are a couple of issues with your code:
Thread.join method works only if the thread has started, else it does nothing. So you must reorder your code, but if you just move the join method after start, when starting the first thread by calling CounterThread.start, the main thread will wait until the started thread has finished, blocked in the Thread.join method, and only then will continue to starting the second one. A solution is to make an additional method in the CounterThread class, that will be called after both threads have been started:
public void waitFinish() throws InterruptedException {
thread.join();
}
synchronized (this) is synchronizing on the CounterThread instance that has been created when you called new CounterThread(...), but you have two instances so each will be synchronizing on a different object. For synchronized to work, you need to use a common instance of an object, in this case you can use the shared counterObj.
Only the AtomicInteger methods are guaranteed to be thread safe, so after you check if the bound has been reached outside the synchronized block, when entering the synchronized block the value can already be changed by another thread. So you need to do a recheck inside the synchronized block OR to first synchronize on the shared lock(counterObj) before the check and increment.
while (true) {
synchronized (counterObj) {
if (counterObj.get() < bound)
counterObj.incrementAndGet();
else break;
}
}
Note that the AtomicInteger class synchronized methods aren't helping now, but because it is a mutable object, it helps to use it as a shared lock. If you used an Integer instead, being immutable, a new instance will have been created when you incremented it. So now, it's only function is a wrapper holding the integer result.
Putting it all together:
public class Application {
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void launch() throws InterruptedException {
int increments = 100;
AtomicInteger counterObj = new AtomicInteger(0);
CounterThread th1 = new CounterThread("1", counterObj, increments);
CounterThread th2 = new CounterThread("2", counterObj, increments);
th1.start();
th2.start();
th1.waitFinish();
th2.waitFinish();
System.out.println(counterObj.get());
}
}
public class CounterThread implements Runnable {
private final String threadID;
private AtomicInteger counterObj;
private int bound;
private Thread thread;
public CounterThread(String threadID, AtomicInteger counter, int bound) {
this.threadID = threadID;
this.counterObj = counter;
this.bound = bound;
}
#Override
public void run() {
while (true) {
synchronized (counterObj) {
if (counterObj.get() < bound)
counterObj.incrementAndGet();
else break;
}
}
System.out.println("Thread " + threadID + " finished");
}
public void start() throws InterruptedException {
thread = new Thread(this, threadID);
thread.start();
}
public void waitFinish() throws InterruptedException {
thread.join();
}
}
I've included a double check on the AtomicInteger, this appears to be what you've been trying to accomplish.
import java.util.concurrent.atomic.AtomicInteger;
public class DualCounters{
public static void main(String[] args) throws Exception{
AtomicInteger i = new AtomicInteger(0);
int bounds = 3;
Thread a = new Thread(()->{
int last = 0;
while(i.get()<bounds){
synchronized(i){
if(i.get()<bounds){
last = i.getAndIncrement();
}
}
}
System.out.println("a last " + last);
});
Thread b = new Thread(()->{
int last = 0;
while(i.get()<bounds){
synchronized(i){
if(i.get()<bounds){
last = i.getAndIncrement();
}
}
}
System.out.println("b last " + last);
});
a.start();
b.start();
a.join();
b.join();
System.out.println(i.get() + " afterwards");
}
}
The double check is a broken concept in java, the AtomicInteger offers tools for accomplishing this without any synchronization.
int a;
while((a = i.getAndIncrement())<bounds){
...
}
Now a will never be greater than bounds inside of the while loop. When the loop is finished i and a could have a value greater than bounds.
If that was an issue, there is always the other method getAndUpdate
while((a = i.getAndUpdate(i->i<bounds?i+1:i)<bounds){
...
}
I have an executor service, and I want to cancel/interrupt the execution of some of the threads.
For example: Below is my Thread class which prints the thread name after some interval infinitely.
public class MyThread implements Runnable {
String name;
public MyThread(String name) {
this.name = name;
}
#Override
public void run() {
try {
System.out.println("Thread "+ name + " is running");
sleep(500);
}catch (InterruptedException e){
System.out.println("got the interrupted signal");
}
}
}
Now I'll create multiple threads by giving them name, so that later on I can stop a particular thread with it's name.
As shown below, I am creating 4 threads and want to stop the execution of 2 threads named foo and bar.
public class ThreadTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
MyThread amit = new MyThread("foo");
MyThread k = new MyThread("bar");
MyThread blr = new MyThread("tel-aviv");
MyThread india = new MyThread("israel");
executorService.submit(foo);
executorService.submit(bar);
executorService.submit(tel-aviv);
executorService.submit(israel);
}
}
Your MyThreads are not actually being run on threads with those names. They're not being run directly as threads, they are run on the ExecutorService's threads.
So, you need to keep a mapping of name to Future, and then cancel the future when you want to.
Map<String, Future<?>> map = new HashMap<>();
map.put("amit", executorService.submit(amit));
map.put("k", executorService.submit(k));
// ... etc
Then, to cancel amit:
map.get("amit").cancel(true);
Of course, you could simply have kept explicit variables:
Future<?> amitFuture = executorService.submit(amit);
amitFuture.cancel(true);
but this might be unwieldy if you have a lot of variables.
I am trying to print numbers from 1 to 10 using three threads. thread 1 prints 1, 2 prints 2, 3 prints 3, 4 is printed by thread 1 again and so on.
I have created a shared printer resource that helps those threads to print number. But I am getting confused as how can i make the number to be visible by all threads.
The problem is eachthread is seeing their own copy of number while I need the same number to be shared by all threads.
I am trying to create this example for learning purposes. I have seen other pages on SO that had same kind of problem but I am not able to get the concept.
Any help is appreciated.
how is this example diffrent from what I am doing?
Printing Even and Odd using two Threads in Java
public class PrintAlternateNumber {
public static void main(String args[]) {
SharedPrinter printer = new SharedPrinter();
Thread t1 = new Thread(new myRunnable2(printer,10,1),"1");
Thread t2 = new Thread(new myRunnable2(printer,10,2),"2");
Thread t3 = new Thread(new myRunnable2(printer,10,3),"3");
t1.start();
t2.start();
t3.start();
}
}
class myRunnable2 implements Runnable {
int max;
SharedPrinter printer;
int threadNumber;
int number=1;
myRunnable2(SharedPrinter printer,int max,int threadNumber) {
this.max=max;
this.printer=printer;
this.threadNumber=threadNumber;
}
#Override
public void run() {
System.out.println(" The thread that just entered run "+ Thread.currentThread().getName());
for(int i =1;i<max;i++){
try {
printer.print(i,threadNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class SharedPrinter {
boolean canPrintFlag=false;
public synchronized void print(int number,int threadNumber) throws InterruptedException{
if(number%3==threadNumber) {
canPrintFlag=true;
}
while(!canPrintFlag)
{
System.out.println(Thread.currentThread().getName() + " is waiting as it cannot print " + number);
wait();
}
System.out.println(Thread.currentThread().getName()+" printed "+number);
canPrintFlag=false;
notifyAll();
}
}
//output
//The thread that just entered run 2
// The thread that just entered run 3
//The thread that just entered run 1
//3 is waiting as it cannot print 1
//1 printed 1
//1 is waiting as it cannot print 2
//3 is waiting as it cannot print 1
//2 is waiting as it cannot print 1
Technique second
it is still incomplete but I am close
output
0printed by0
2printed by2
1printed by1
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
class AlternateNumber {
public static void main(String args[]) {
printerHell ph = new printerHell();
BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10);
for(int i=0;i<10;i++)
{
queue.add(i);
}
Thread t1 = new Thread(new myRunnableHell(queue,0,ph),"0");
Thread t2 = new Thread(new myRunnableHell(queue,1,ph),"1");
Thread t3 = new Thread(new myRunnableHell(queue,2,ph),"2");
t1.start();
t2.start();
t3.start();
}
}
class myRunnableHell implements Runnable {
BlockingQueue<Integer> queue;
int threadNumber;
printerHell ph;
myRunnableHell(BlockingQueue<Integer> queue, int threadNumber,printerHell ph) {
this.queue=queue;
this.threadNumber=threadNumber;
this.ph=ph;
};
int currentNumber;
#Override
public void run() {
for(int i=0;i<queue.size();i++)
{
currentNumber=queue.remove();
if(threadNumber%3==currentNumber)
{
ph.print(currentNumber);
}
}
}
}
class printerHell {
public synchronized void print(int Number)
{
System.out.println(Number + "printed by" + Thread.currentThread().getName());
}
}
Please see my solution here..
Using simple wait/notify
https://stackoverflow.com/a/31668619/1044396
Using cyclic barriers:
https://stackoverflow.com/a/23752952/1044396
For your query on 'How different it is from even/odd thread problem.
--> it is almost same ... instead of maintaining two states have one more state to call the third thread, so I believe,this can be extended any number of threads.
EDIT:
You may view this approach when you want to have 'n' number of threads to do the work sequentially.(Instead of having different classes t1,t2,t3 etc)
https://codereview.stackexchange.com/a/98305/78940
EDIT2:
Copying the code here again for the above solution
I tried to solve using a single class 'Thrd' which gets initialized with its starting number.
ThreadConfig class which as size of total number of threads you want to create.
State class which maintains the state of the previous thread.(to maintain ordering)
Here you go..(please review and let me know your views)
EDIT:
How it works -->
when a thread Tx gets a chance to execute.. it will set state variable's state with x. So a next thread(Tx+1) waiting , will get a chance once state gets updated. This way you can maintain the ordering of threads.
I hope i am able to explain the code. Please run it and see or let me know for any specific queries on the below code
1)
package com.kalyan.concurrency;
public class ThreadConfig {
public static final int size = 5;
}
2) package com.kalyan.concurrency;
public class State {
private volatile int state ;
public State() {
this.state =3;
}
public State(int state) {
this.state = state;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
}
3) package com.kalyan.concurrency;
public class Thrd implements Runnable {
int i ;
int name;
int prevThread;
State s;
public Thrd(int i,State s) {
this.i=i;
this.name=i;
this.prevThread=i-1;
if(prevThread == 0) prevThread=ThreadConfig.size;
this.s=s;
}
#Override
public void run() {
while(i<50)
{
synchronized(s)
{
while(s.getState() != prevThread)
{
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
synchronized(s)
{
//if(s.getState() ==3)
if(s.getState()==prevThread)
System.out.println("t"+ name+ i);
s.setState(name);
i = i +ThreadConfig.size ;
s.notifyAll();
}
}
}
}
4)
package com.kalyan.concurrency;
public class T1t2t3 {
public static void main(String[] args) {
State s = new State(ThreadConfig.size);
for(int i=1;i<=ThreadConfig.size;i++)
{
Thread T = new Thread(new Thrd(i,s));
T.start();
}
}
}
OUTPUT:
t11
t22
t33
t44
t55
t16
t27
t38
t49
t510
t111
t212
t313
t414
t515
t116..............
I hope I understood you right, but there are to main "features" in java to make a variable being shared between threads:
the volatile keyword
volatile int number = 1;
AtomicInteger (a standard java class -> no library)
AtomicInteger number = new AtomicInteger(1);
These two techniques should both do what you want, however I have no experience using it, I just came upon this word, didn't know what it means and did some digging.
Some stuff to read: ;)
volatile for java explained --> http://java.dzone.com/articles/java-volatile-keyword-0
a better explanation (with IMAGES!!) but for c# (which is still the same usage) --> http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/
And a link to some usages of AtomicInteger --> https://stackoverflow.com/a/4818753/4986655
I hope I could help you or at least send you in the right direction :)
- superfuzzy
I want to restart a thread for some use, for example in the below code.
class Ex13 implements Runnable {
int i = 0;
public void run() {
System.out.println("Running " + ++i);
}
public static void main(String[] args) throws Exception {
Thread th1 = new Thread(new Ex13(), "th1");
th1.start();
//th1.join()
Thread th2 = new Thread(th1);
th2.start();
}
}
When I'm executing the above program , some time i'm getting the output as
Running 1
Running 2
and some time i'm getting only
Running 1
After few run i'm getting only
Running 1 as output.
I'm totally surprise about this behavior. Can any one help me understand this.
if I put the join() then i'm getting only Running 1.
You reuse Thread instance, not Runnable. Thread overwrites its run() method to
public void run() {
if (target != null) {
target.run();
}
}
Where target is the Runnable that you give to the constructor. besides that, Thread has an exit() method that is called by the VM, and this method sets target to null (the reason is this bug). So if your first thread has the chance to finish its execution, its run() method is pretty much empty. Adding th1.join() proves it.
If you want to keep some state, you need to keep reference to your Runnable instance, not the Thread. This way run() method will not be altered.
I don't know why do you need this, but (please note that this code doesn't ensure that th1 is ALWAYS executed before th2, though) :
public static class Ex13 implements Runnable {
AtomicInteger i = new AtomicInteger(0);
CountDownLatch latch;
Ex13(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
System.out.println("Running " + i.incrementAndGet());
latch.countDown();
}
}
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(2);
Ex13 r = new Ex13(latch);
Thread th1 = new Thread(r, "th1");
th1.start();
Thread th2 = new Thread(r);
th2.start();
latch.await(); // wait until both theads are executed
System.out.println("Done");
}
You want the incrementing of i to be synchronized, i.e.
public class Ex13 implements Runnable {
int i=0;
public void run() {
System.out.println("Running "+ increment());
}
private synchronized int increment() {
return ++i;
}
}
The Java Tutorial has a very nice explanation of this given a very similar scenario. The problem is that incrementing a variable is not an atomic operation. Each thread needs to read the current state of i before setting it to the new value. Restricting access to incrementing the variable to one thread at a time assures you will get consistent behavior.
To see whats happening in the System.out.println you can also print the thread name:
Thread t = Thread.currentThread();
String name = t.getName();
System.out.println("name=" + name);
I see you call the two threads with the same runnable object, so they will both use the same "i" variable, in order for you to get Running 1 Running 2 you need to synchronize "i"
For example I need to always run 100 threads to do some action.
I have class which called ThreadsWorker which looks for threads count and runs missing threads if some previous are finished.
So, this is the table which describes situation:
1 second: 100 threads
2 second: 92 threads (ThreadsWorker generates new 8 threads)
3 second: 100 theads
4 second: 72 threads (ThreadsWorker generates 28 threads)
And so on.
My threads are anonymous calls (just new Thread(new Runnable(...)).start()) because I don't know how to correctly save them to Threads[] array because, while ThreadsWorker will save threads[i] = new Threads(), some threads may be finished and then there will be some collision with array indexes.
Because of anonymous calls I use threadsCount variable now and increment it in threads body beginning and decrements in threads body end (using synchronized). Okay, it works correctly and my single way is to use while() loop which checks if threadsCount == 0 when the progress is complete.
I think that this is C-style but not Java-way :) So, can you help me to do it in Java-way?
If your goal is simply to have 100 threads actively processing, I suggest looking at Java thread pools (and Executors more generally).
I'm unclear as to whether you want to keep all 100 threads going or wait for them all to finish. Your question references both (ThreadsWorker spawning 28 new threads, threadsCount==0) and they seem contradictory.
Put all the threads into an array or collection.
Then loop through the collection calling Thread.join() on each. When this loop completes, all threads are done.
ArrayList threads = new ArrayList();
for (int i = 0; i < 5; i++) {
Thread t = new AweseomeThread();
t.start();
threads.add(t);
}
for (Thread t : threads) {
t.join();
}
You'll need some exception handling too (such as InterruptedException). But, I'll leave that as an exercise for the reader... :)
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html
You can try class CountDownLatch jdk api
private CountDownLatch latch;
private static class SimpleThread extends Thread {
public void run() {
latch.countDown();
}
}
public static void main(String[] args) {
int threadcount = 10;
latch = new CountDownLatch(threadcount);
for (int i = 0; i < 10; i++) {
Thread t = new SimpleThread();
t.start();
}
// waiting threads all finished
latch.await();
}
Fetch the thread count from attibute latch of the Main class
I believe you are trying to have ThreadWorker submit new threads for all thread that have been completed.
I'd use a BlockingQueue that threads (Your Runnable(s)) add to when complete. ThreadWorker will wait until a thread completes and then will start a new thread.
public class YourRunnable implements Runnable {
private final BlockingQueue<YourRunnable> queue;
public YourRunnable(BlockingQueue<YourRunnable> queue){
this.queue = queue;
}
public void run{
// Your Code...
// Finished Processing
queue.add(this);
}
}
public class ThreadWorkder implements Runnable {
private final BlockingQueue<YourRunnable> queue;
ThreadWorker(BlockingQueue<YourRunnable> queue){
this.queue = queue;
}
public void run{
while(queue.take()){
(new Thread(new YourRunnable(queue))).start();
}
}
// general main method
public static void main(String [] args){
BlockingQueue<YourRunnable> queue = new LinkedBlockingQueue<YourRunnable>();
ThreadWorker worker = new ThreadWorker(queue);
Thread(worker).start();
for (int i = 0; i < 100; i++){
(new Thread(new YourRunnable(queue))).start();
}
}
}
Use a collection instead of an array. As the threads are completed, have them remove themselves from the array. Something like this:
public class Foo {
Vector<Thread> threads = new Vector<Thread>(); //Vector is threadsafe
public ensureThreadCount(int count) {
while (threads.size() < count) {
Thread t = new AweseomeThread(threads);
threads.add(t);
t.start();
}
}
}
public class AwesomeThread {
Collection threads;
public AwesomeThread(Collection threads) {
this.threads = threads;
}
public void run() {
try {
// do stuff
} catch (Throwable t) {
} finally {
threads.remove(this);
}
}
}
Then, have your worker just call Foo.ensureThreadCount().