I have to do schoolwork, and I have some code done, but got some questions:
must create a boss-workers application in java.
I have these classes: Main WorkerThread BossThread Job
Basically what I want to do is, that BossThread holds a BlockingQueue and workers go there and look for Jobs.
Question 1:
At the moment I start 5 WorkingThreads and 1 BossThread.
Main:
Collection<WorkerThread> workers = new ArrayList<WorkerThread>();
for(int i = 1; i < 5; i++) {
WorkerThread worker = new WorkerThread();
workers.add(worker);
}
BossThread thread = new BossThread(jobs, workers);
thread.run();
BossThread:
private BlockingQueue<Job> queue = new ArrayBlockingQueue<Job>(100);
private Collection<WorkerThread> workers;
public BossThread(Set<Job> jobs, Collection<WorkerThread> workers) {
for(Job job : jobs) {
queue.add(job);
}
for(WorkerThread worker : workers) {
worker.setQueue(queue);
}
this.workers = workers;
}
Is this normal, or I should create WorkerThreads in my BossThread ?
Question 2:
As you see I am giving the queue to each WorkerThread , is that reasonable or I could store the queue only in one place?
Question 3:
Must I keep my BossThread running somehow, just to wait if user adds more stuff to queue? And how I keep WorkerThreads running, to look for jobs from queue?
Any overall suggestions or design flaws or suggestions?
public class WorkerThread implements Runnable {
private BlockingQueue<Job> queue;
public WorkerThread() {
}
public void run() {
try {
queue.take().start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void setQueue(BlockingQueue<Job> queue) {
this.queue = queue;
}
}
Firstly, one important mistake I noticed:
BossThread thread = new BossThread(jobs, workers));
thread.run();
Runnables must be passed to a Thread object and threads are started with start, not run. By calling run you get sequential execution on the same thread. So:
Thread thread = new Thread(new BossThread(jobs, workers)));
thread.start();
Secondly, unless you absolutely must use BlockingQueue and explicit threads I would instead use ExecutorService. It neatly encapsulates a blocking work queue and a team of workers (whose size you can set). It's basically what you're doing but much simpler to use:
class Job implements Runnable {
public void run() {
// work
}
}
...
// create thread pool with 5 threads and blocking queue
ExecutorService exec = Executors.newFixedThreadPool(5);
// submit some work
for(int i = 0; i < 10; i++) {
exec.submit(new Job());
}
And that's it! All the put and take stuff is handled by the executor automatically.
Related
I am creating a fixed-size thread pool with 10 threads as follows:
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < poolSize; ++i) {
executorService.execute(factory.get());
}
Now, after spawning 10 threads, a runnable is being executed by each of them. Runnable here is provided by factory.get()
Now, I wanted to do a thing that as soon as a thread gets shutdown, i.e. it has completed a task, it picks another runnable again and start running it. So, basically check for all 10 threads state and execute a runnable again if the thread is shutdown.
I know I can do something like, in which I can call the executorService shutdown() method as follows to do that:
while (!executorService.isShutdown()) {
try {
executorService.execute(factory.get());
} catch (RejectedExecutionException e) {
if (!executorService.isShutdown())
log.warn("task submission rejected");
}
}
But in this approach, issue is that I am keep on calling the execute function which would increase LinkedBlockingQueue and won't serve my purpose.
If I can somehow check the Threads state, that would be good because then, it would avoid the overhead of going back to get more work from the executor service.
Please suggest how can I do that in code.
You can use a bounded executor. The following is code by Brian Goetz from jcip
/**
* BoundedExecutor
* <p/>
* Using a Semaphore to throttle task submission
*
* #author Brian Goetz and Tim Peierls
*/
public class BoundedExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound) {
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command)
throws InterruptedException {
semaphore.acquire();
try {
exec.execute(new Runnable() {
public void run() {
try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
}
}
}
Then just create and use it:
ExecutorService executorService = Executors.newFixedThreadPool(10);
BoundedExecutor boundedExecutor = new BoundedExecutor(executorService,10);
while (!executorService.isShutdown()) {
try {
boundedExecutor.submitTask(factory.get());
} catch (InterruptedException e) {
}
}
This way you will always have 10 threads running, new tasks will only be submitted after the old ones will complete and you can stop the execution by shutting down the executor.
Why use a thread pool if you're going to run 10 threads continually? Just start 10 threads yourself.
Why have a "controller" thread on top of the 10 worker threads? Just let each thread ask for the next task to execute.
The following assumes that factory.get() is thread-safe.
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (;;) {
Runnable r = factory.get(); // <-- must be thread-safe
if (r == null)
break; // stop thread if no more tasks to execute
try {
r.run();
} catch (Exception e) {
// log exception here
}
}
}).start();
}
If needed, save the 10 thread objects in an array.
If you want to be able to shutdown the threads without having factory.get() returning null, add a volatile boolean, and check it in the loop.
I know that a java thread cannot be restarted. So when I submit more than one tasks to newSingleThreadExecutor, then how does it perform all tasks using single thread?
My understanding is that newSingleThreadExecutor will use maximum one thread at a time to process any submitted tasks. I guess same for newFixedThreadPool.
If a Thread cannot be restarted then for performing n tasks, n threads should be spawned. I think newSingleThreadExecutor, newFixedThreadPool will make sure that not many threads should be spawned at a same time, like we do without using ExecutorService (where we attach each task with a thread and start separately)
Here is code example
class Task implements Runnable {
public void run() {
System.out.println("ThreadID-" + Thread.currentThread().getId());
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
}
}
}
public class SingleThreadExecutorTest {
public static void main(String[] args) {
System.out.println("ThreadID-" + Thread.currentThread().getId());
ExecutorService ex = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
ex.execute(new Task());
}
}
}
The above code always prints the same ThreadID.
If I replace below line
Executors.newSingleThreadExecutor();
with
ExecutorService ex = Executors.newFixedThreadPool(2);
Then again it is able to perform all tasks using 2 Threads.
Only when I use
Executors.newCachedThreadPool();
I see different Thread IDs.
How does ExecutorService reuse a Thread?
Does it not let it reach to Dead State?
The ThreadPoolExecutor maintains some Worker threads, which work like this:
public class Demo {
public class Worker implements Runnable {
#Override
public void run() {
Runnable task = getTaskFromQueue();
while (task != null) {
task.run();
task = getTaskFromQueue(); // This might get blocked if the queue is empty, so the worker thread will not terminate
}
}
}
public static void main(String[] args) {
Worker worker = new Worker();
Thread thread = new Thread(worker);
thread.start();
}
}
When you submit a task to ThreadPoolExecutor which has a single Worker thread, the calling threads will put the task into a BlockingQueue on below condition:
the single Worker is busy
the BlockingQueue is not full
And when the Worker is free, it will retrieve new task from this BlockingQueue.
I was wondering what the best way to create a Java Thread that does not terminate.
Currently, I basically have a "Runner" that basically looks like:
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i = 0; i < numThreads; ++i) {
pool.submit(new Task());
}
pool.shutdown();
and Task looks something like this
public class Task {
...
public void run() {
while(true) { }
}
}
There are two concerns I have with my approach:
Should I be creating a task that just returns after doing work and continue spawning threads that do minimal amounts of work? I'm concerned about the overhead, but am not sure how to measure it.
If I have a Thread that just loops infinitely, when I force quit the executable, will those Threads be shutdown and cleaned up? After some testing, it doesn't appear an InterruptException is being thrown when the code containing the ExecutorService is forcefully shutdown.
EDIT:
To elaborate, the Task looks like
public void run() {
while(true) {
// Let queue be a synchronized, global queue
if (queue has an element) {
// Pop from queue and do a very minimal amount of work on it
// Involves a small amount of network IO (maybe 10-100 ms)
} else {
sleep(2000);
}
}
}
I agree with #D Levant, Blocking queue is the key to use here. With blocking queue, you don't need to handle the queue-empty or queue-full scenario.
In your Task class,
while(true) {
// Let queue be a synchronized, global queue
if (queue has an element) {
// Pop from queue and do a very minimal amount of work on it
// Involves a small amount of network IO (maybe 10-100 ms)
} else {
sleep(2000);
}
}
Its really not a good approach, its inefficient because your while loop is continuously polling, even you have put the thread sleep(), but still its also a overhead of unnecessary context-switches every time the thread wake-ups and sleeps.
In my opinion, your approach of using Executors is looking good for your case. Thread creation is obviously a costly process, and Executors provide us the flexibility of re-using the same thread for different tasks.
You can just pass your task through execute(Runnable) or submit(Runnable/Callable) and then rest will be taken care by Executors internally. Executors internally uses blocking queue concept only.
You can even create your own thread pool by using the ThreadPoolExecutor class and passing the required parameter in its constructor, here you can pass your own blocking queue to hold the tasks. Rest thread-management will be taken care by it on basis of the configuration passes in constructor, So If you are really confident about the configuration parameters then you can go for it.
Now the last point, If you don't want to use the Java's in-built Executors framework, then you can design your solution by using BlockingQueue to hold tasks and starting a thread which will take the tasks from this blocking queue to execute, Below is the high-level implementation:
class TaskRunner {
private int noOfThreads; //The no of threads which you want to run always
private boolean started;
private int taskQueueSize; //No. of tasks that can be in queue at a time, when try to add more tasks, then you have to wait.
private BlockingQueue<Runnable> taskQueue;
private List<Worker> workerThreads;
public TaskRunner(int noOfThreads, int taskQueueSize) {
this.noOfThreads = noOfThreads;
this.taskQueueSize = taskQueueSize;
}
//You can pass any type of task(provided they are implementing Runnable)
public void submitTask(Runnable task) {
if(!started) {
init();
}
try {
taskQueue.put(task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void shutdown() {
for(Worker worker : workerThreads){
worker.stopped = true;
}
}
private void init() {
this.taskQueue = new LinkedBlockingDeque<>(taskQueueSize);
this.workerThreads = new ArrayList<>(noOfThreads);
for(int i=0; i< noOfThreads; i++) {
Worker worker = new Worker();
workerThreads.add(worker);
worker.start();
}
}
private class Worker extends Thread {
private volatile boolean stopped;
public void run() {
if(!stopped) {
try {
taskQueue.take().run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class Task1 implements Runnable {
#Override
public void run() {
//Your implementation for the task of type 1
}
}
class Task2 implements Runnable {
#Override
public void run() {
//Your implementation for the task of type 2
}
}
class Main {
public static void main(String[] args) {
TaskRunner runner = new TaskRunner(3,5);
runner.submitTask(new Task1());
runner.submitTask(new Task2());
runner.shutdown();
}
}
Thread Pool like any ExecutorServices, we defined a newFixedPool of size 3. Now I have a queue of around 10000 runnable tasks.
For executing the above process I have these doubts -
To execute the above process , is the executor will let only 3 threads from the queus of tasks to run in one shot?
The Pool will be carrying 3 Threads , and those 3 threads will only be responsible for executing all the 10000 tasks. If it is correct , how a single thread is running different runnable tasks as finally those tasks are as well threads itself , and in the mid of the running of any of the job/tasks , you can assign new responsibility to the Pool Thread.
Yes, at most only 3 threads will be in the pool at once if in fact you are using Executors.newFixedThreadPool(3)
The 10,000 tasks are not Threads they are simply Runnables. A Thread has to be started via Thread#start to actually create a system thread. Tasks (instances of Runnable) are placed in a BlockingQueue. Threads from the thread pool will poll the BlockingQueue for a task to run. When they complete the task, they return to the queue to get another. If more tasks are added, then they are inserted into the BlockingQueue according to the rules of the implementation of that queue. For most queues this is First-In-First-Out, but a PriorityQueue actually uses a Comparator or natural ordering to sort tasks as they are inserted.
Below is customThreadPool in java which accept noofThreads and MaxConcurrentTask.
Also it has stop() to stop complete ThreadPool
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
#SuppressWarnings("all")
public class ThreadPool {
private BlockingQueue taskQueue = null;
private List<PoolThread> threads = new ArrayList<PoolThread>();
private boolean isStopped = false;
public ThreadPool(int noOfThreads, int maxNoOfTasks) {
taskQueue = new LinkedBlockingQueue(maxNoOfTasks);
for(int i=0; i<noOfThreads; i++) {
threads.add(new PoolThread(taskQueue));
}
for(PoolThread thread : threads) {
thread.start();
}
}
public synchronized void execute(Runnable task) {
if(this.isStopped)
throw new IllegalStateException("ThreadPool is stopped");
this.taskQueue.offer(task);
}
public synchronized void stop() {
this.isStopped = true;
for(PoolThread thread : threads) {
thread.stopMe();
}
}
}
#SuppressWarnings("all")
class PoolThread extends Thread {
private BlockingQueue taskQueue = null;
private boolean isStopped = false;
public PoolThread(BlockingQueue queue) {
taskQueue = queue;
}
public void run() {
while(!isStopped()) {
try {
Runnable runnable = (Runnable) taskQueue.poll();
runnable.run();
} catch(Exception e) {
//log or otherwise report exception, //but keep pool thread alive.
}
}
}
public synchronized void stopMe() {
isStopped = true;
this.interrupt();
//break pool thread out of dequeue() call.
}
public synchronized boolean isStopped() {
return isStopped;
}
}
I'm writing a load-testing application in Java, and have a thread pool that executes tasks against the server under test. So to make 1000 jobs and run them in 5 threads I do something like this:
ExecutorService pool = Executors.newFixedThreadPool(5);
List<Runnable> jobs = makeJobs(1000);
for(Runnable job : jobs){
pool.execute(job);
}
However I don't think this approach will scale very well, because I have to make all the 'job' objects ahead of time and have them sitting in memory until they are needed.
I'm looking for a way to have the threads in the pool go to some kind of 'JobFactory' class each time they need a new job, and for the factory to build Runnables on request until the required number of jobs have been run. The factory could maybe start returning 'null' to signal to the threads that there is no more work to do.
I could code something like this up by hand, but it seems like a common enough use-case and was wondering if there was anything in the wonderful but complex 'java.util.concurrent' package that I could use instead?
You can do all the work in the executing threads of the thread pools using an AtomicInteger to monitor the number of runnables executed
int numberOfParties = 5;
AtomicInteger numberOfJobsToExecute = new AtomicInteger(1000);
ExecutorService pool = Executors.newFixedThreadPool(numberOfParties );
for(int i =0; i < numberOfParties; i++){
pool.submit(new Runnable(){
public void run(){
while(numberOfJobsToExecute.decrementAndGet() >= 0){
makeJobs(1).get(0).run();
}
}
});
}
You can also store the returned Future's in a List and get() on them to await completion (among other mechanisms)
Hrm. You could create a BlockingQueue<Runnable> with a fixed capacity and have each of your worker threads dequeue a Runnable and run it. Then you could have a producer thread which is what puts the jobs into the queue.
Main thread would do something like:
// 100 is the capacity of the queue before blocking
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(100);
// start the submitter thread
new Thread(new JobSubmitterThread(queue)).start();
// make in a loop or something?
new Thread(new WorkerThread(queue)).start();
new Thread(new WorkerThread(queue)).start();
...
The worker would look something like:
public class WorkerThread implements Runnable {
private final BlockingQueue<Runnable> queue;
public WorkerThread(BlockingQueue<Runnable> queue) {
this.queue = queue;
}
public void run() {
// run until the main thread shuts it down using volatile boolean or ...
while (!shutdown) {
Runnable job = queue.take();
job.run();
}
}
}
And the job submitter would look something like:
public class JobSubmitterThread implements Runnable {
private final BlockingQueue<Runnable> queue;
public WorkerThread(BlockingQueue<Runnable> queue) {
this.queue = queue;
}
public void run() {
for (int jobC = 0; jobC < 1000; jobC++) {
Runnable job = makeJob();
// this would block when the queue reaches capacity
queue.put(job);
}
}
}