new to multithreading here please bear with me.
I'm trying to run 2 threads which remove items from a list of tasks (10 tasks in total) until the taskList is empty.
What i have so far is:
Main method:
public static void main(String[] args) {
List<Task> taskList = new ArrayList<Task>();
List<Thread> threadList = new ArrayList<Thread>();
for (int i = 1; i <= 10; i++) {
taskList.add(new Task("some details");
}
TaskManager manager = new TaskManager();
gestor.setTaskList(taskList);
Thread t1 = new Thread(taskManager);
Thread t2 = new Thread(taskManager);
threadList.add(t1);
threadList.add(t2);
if(threadList.size() > 0){
for (Thread thread : threadList){
thread.start();
}
}
for (Thread thread : threadList){
try {
thread.join();
} catch (InterruptedException e) {
System.out.println("thread " + Thread.currentThread().getName() + " was interrupted");
}
}
System.out.println("END OF MAIN");
}
Task Manager class:
public class TaskManager implements Runnable {
private List<Task> availableTasks;
private Random random = new Random();
public void setAvailableTasks(List<Task> availableTasks) {
this.availableTasks = availableTasks;
}
#Override
public void run() {
while (!availableTasks.isEmpty()) {
takeTask();
}
}
public void takeTask() {
try {
Thread.sleep(1000);
int index = random.nextInt(availableTasks.size());
Task task = availableTasks.get(index);
printDetails(task);
availableTasks.remove(task);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void printDetails(Task task) {
//here it should print the details to the console
}
}
The thing is, it either runs 2 times or it's always the same thread running 10 times. I know it's probably a silly question but I hope someone can clarify it! Thanks in advance
Edit: I was able to make it work using #Lidae's suggestion
Take task method edited like so:
public void takeTask() {
try {
Thread.sleep(1000);
synchronized (this) {
if (!availableTasks.isEmpty()) {
int index = random.nextInt(availableTasks.size());
Task task = availableTasks.get(index);
printDetails(task);
availableTasks.remove(task);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Your code has some concurrency problems as a result of several threads trying to access the same object at the same time. For example one thing that can happen is that thread A gets a task from the list (in Task task = availableTasks.get(index)), then there is a context switch and that very task is removed by thread B, and by the time thread A tries to remove the task, it is already gone (this wouldn't cause an exception in your code, but it could be bad anyway depending on what exactly you plan on doing with the task).
You also can't be sure that the list is not empty when you try to get a task from it: it was empty when it last checked in the while-loop, but between then and the time that it attempts to take a task, another thread might have already taken the last task. This is true even if you remove the call to Thread.sleep.
What you need to is make sure that the availableTasks list is only modified by one thread at a time. This can be done in various ways, for example by using a Semaphore, or by using synchronized methods in the shared data object.
it's always the same thread running 10 times
My guess is because your list is too small, so first thread runs and finishes the job before second thread have a chance to start working. Make task list longer, like 1000+ tasks, maybe even more.
it either runs 2 times
this is probably because your task list is not thread safe, make it thread safe using Collections.SynchronizedList
for (int i = 1; i <= 10; i++) {
taskList.add(new Task("some details");
}
taskList = Collections.synchronizedList(taskList);
TaskManager manager = new TaskManager();
Can't reproduce this.
I've corrected (quite a few) compilation problems with your code and ran it, getting:
Thread-1 printing some details for task 5
Thread-0 printing some details for task 8
Thread-0 printing some details for task 2
Thread-1 printing some details for task 7
Thread-1 printing some details for task 1
Thread-0 printing some details for task 3
Thread-0 printing some details for task 6
Thread-1 printing some details for task 9
Thread-0 printing some details for task 4
Thread-1 printing some details for task 0
So both threads run and process tasks.
One thing which is important is that the access to the list of tasks should be synchronized. And not just Collections.synchronizedList, you have at least four places where you access your list of tasks. This is why the execution of the program almost always ends with:
java.lang.IllegalArgumentException: n must be positive
at java.util.Random.nextInt(Random.java:250)
at TaskManager.takeTask(TaskManager.java:25)
at TaskManager.run(TaskManager.java:18)
at java.lang.Thread.run(Thread.java:662)
Your TaskManager.run method first check for isEmpty and then gets a random task from the list. Another thread may remove the last task of the list between these two operations. Resulting in random.nextInt(0) despite you've previously checked that the list is not empty.
Better would be something like:
private Task nextTask() {
synchronize(availableTask) {
if (availableTask.isEmpty()) {
return null;
} else {
return availableTasks.get(random.nextInt(availableTasks.size()));
}
}
}
Adding to what #Lidae answered. It is standard multiple-producer to multiple-consumer problem. There are couple of articles on the same..
Related
I have these 5 simple thread that run a while loop:
flasherThread = new Thread(new Runnable() {
#Override
public void run() {
while(running.get()) {
// do network stuff
}
}
});
running is declared as private final AtomicBoolean running;.
I have this method:
public void stopFlasherThread() {
running.set(false);
}
My question is by setting the flag to false that stops the thread immediately ? Or do I need to call flasherThread.join() to make sure that the thread has stopped ?
The main issue is that I have 4-5 of these at a time.
So I have a loop such as:
for (int i = 0; i < 5; i++) {
ThreadArrayList.get(i).stopFlasherThread();
ThreadArrayList.get(i).join() // should I do this ?
}
Any help would be great! Thanks
According to the official documentation on join:
The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing,
t.join();
causes the current thread to pause execution until t's thread terminates.
So, no... or not necessarily, only if you need the result of the work of that thread to do something. The join will not stop / interrupt the thread, it will wait for it to finish its work. The stopFlasherThread will make the loop stop.
I would advise you to follow a different approach on using threads on Java using ExecutorService. For example:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<AtomicInteger> futureResult = executor.submit(new Callable<AtomicInteger>() {
#Override
public AtomicInteger call() {
// Here I return a random integer, but you can do your proper calculation
AtomicInteger atomicInteger =
new AtomicInteger(ThreadLocalRandom.current().nextInt());
System.out.println(Thread.currentThread().getName() + " " + atomicInteger);
return atomicInteger;
}
});
// Thread returns result, but continues to execute as it is a single thread pool
try {
System.out.println(Thread.currentThread().getName() + " " + futureResult.get());
} catch (InterruptedException e) {
// Handle exception properly
e.printStackTrace();
} catch (ExecutionException e) {
// Handle exception properly
e.printStackTrace();
}
// Stop all threads
executor.shutdownNow();
There I define an inline class that extends the Callable interface and implement the call method to perform a task in another thread. This returns the result of the computation in the variable futureResult which is a Future. Since executor is a thread pool, it continues to be available to take tasks even though our task here has already been resolved. To finish the whole thread pool loop you can do a executor.shutdownNow().
I am new to multithreading. I am trying to write a program where I have two threads. One thread prints odd number and then gives up the monitor lock using wait() and similarly other thread prints the even number and gives up the lock after printing the number
I have got 4 classes
Odd.java (print odd numbers between 1-100)
Even.java(print even number between 1-100)
SomeMaths.java( has got logic for printing odd and even numbers )
OEApp.java (Main class that starts the threads)
Problem - My code works as expected most of the times i.e it print number 1 to 100 in order. Both the thread take turns. But I noticed that there is a bug.Sometimes the even thread gets scheduled first and gets below output
2 **********
1 ###############################
After that nothing gets printed, Looks like there is a deadlock situation. I am not able to figure out why. Please help me to understand this
public class SomeMaths {
public synchronized void printOdd(){
for( int i=1;i<=100;i++){
if(i%2 !=0) {
System.out.println(i + " ###############################");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
notify();
}
}
public synchronized void printEven(){
for(int i=1;i<=100;i++){
if(i%2 ==0){
System.out.println(i +" **********");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
notify();
}
}
}
public class Odd implements Runnable {
SomeMaths sm;
public Odd(SomeMaths sm){
this.sm = sm;
}
#Override
public void run(){
sm.printOdd();
}
}
public class Even extends Thread {
SomeMaths sm;
public Even(SomeMaths sm){
this.sm = sm;
}
#Override
public void run(){
sm.printEven();
}
}
public class OEApp {
public static void main(String[] args) {
SomeMaths sm = new SomeMaths();
Thread odd = new Thread(new Odd(sm));
Thread even = new Thread(new Even(sm));
odd.start();
even.start();
try {
odd.join();
even.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I believe it works this way:
Even thread starts, 1 is odd so it calls notify (notifying no one), then 2 is even so it prints a message and waits
Odd thread starts, 1 is odd so it prints a message and waits
There's no one to call notify so both threads wait forever
What is your purpose for using the synchronize keyword ?
It can only assure you that your function will not be running multiple times at the same time.
I assume that you want one thread to notify another ? Is that right ?
But what if the notify is called before the wait occurred ?
You know that you can use the debugger to see each thread, and thus know where each thread is stuck ?
Please keep in mind, once start is called, you can't know which thread will have cpu time.
Furthermore you are trying to synchronize two threads (by the use of the notify/wait mecanism), but there are other mecanisms that will be proved simpler (e.g. semaphore: each thread having it own semaphore, acquiring it own semaphore and releasing the other one semaphore; initialize each semaphore to 1 and it will go smoothly).
P.S. :
I am forced to post an answer, but it should be a comment; sorry
Why use both runnable and thread interface ? Furthermore your Even class is already a thread, so no use to wrap it once again.
See https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem
My program has an arraylist of websites which I do I/O with image processing, scrape data from sites and update/insert into database. Right now it is slow because all of the I/O being done. I would like to speed this up by allowing my program to run with threads. Nothing is ever removed from the list and every website in the list is separate from each other so to me it seems okay to have instances looping through the list at the same time to speed this up.
Let's say my list is 10 websites, right now of course it's looping through position 0 through 9 until my program is done processing for all websites.
And let's say I want to have 3 threads looping through this list of 10 websites at once doing all the I/O and database updates in their own separate space at the same time but using the same list.
website.get(0) // thread1
website.get(1) // thread2
website.get(2) // thread3
Then say if thread2 reaches the end of the loop it first it comes back and works on the next position
website.get(3) // thread2
Then thread3 completes and gets the next position
website.get(4) // thread3
and then thread1 finally completes and works on the next position
website.get(5) // thread1
etc until it's done. Is this easy to set up? Is there somewhere I can find a good example of it being done? I've looked online to try to find somewhere else talking about my scenario but I haven't found it.
In my app, I use ExecutorService like this, and it works well:
Main code:
ExecutorService pool = Executors.newFixedThreadPool(3); //number of concurrent threads
for (String name : website) { //Your ArrayList
pool.submit(new DownloadTask(name, toPath));
}
pool.shutdown();
pool.awaitTermination(5, TimeUnit.SECONDS); //Wait for all the threads to finish, adjust as needed.
The actual class where you do the work:
private static class DownloadTask implements Runnable {
private String name;
private final String toPath;
public DownloadTask(String name, String toPath) {
this.name = name;
this.toPath = toPath;
}
#Override
public void run() {
//Do your parsing / downloading / etc. here.
}
}
Some cautions:
If you are using a database, you have to ensure that you don't have two threads writing to that database at the same time.
See here for more info.
As mentioned in other comments/answer you just need a thread pool executor with fixed size (say 3 as per your example) which runs 3 threads which iterate over the same list without picking up duplicate websites.
So apart from thread pool executor, you probably need to also need to correctly work out the next index in each thread to pick the element from that list in such a way that thread does not pick up same element from list and also not miss any element.
Hence i think you can use BlockingQueue instead of list which eliminates the index calculation part and guarantees that the element is correctly picked from the collection.
public class WebsitesHandler {
public static void main(String[] args) {
BlockingQueue<Object> websites = new LinkedBlockingQueue<>();
ExecutorService executorService = Executors.newFixedThreadPool(3);
Worker[] workers = new Worker[3];
for (int i = 0; i < workers.length; i++) {
workers[i] = new Worker(websites);
}
try {
executorService.invokeAll(Arrays.asList(workers));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static class Worker implements Callable {
private BlockingQueue<Object> websites;
public Worker(BlockingQueue<Object> websites) {
this.websites = websites;
}
public String call() {
try {
Object website;
while ((website = websites.poll(1, TimeUnit.SECONDS)) != null) {
// execute the task
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return "done";
}
}
}
I think you need to update yourself with latest version of java i.e Java8
And study about Streams API,That will definitely solve your problem
I have hundreds of files to process. I do each file one at a time and it takes 30 minutes.
I'm thinking I can do this processing in 10 simultaneous threads, 10 files at a time, and I might be able to do it in 3 minutes instead of 30.
My question is, what is the "correct" way to manage my 10 threads? And when one is done, create a new one to a max number of 10.
This is what I have so far ... is this the "correct" way to do it?
public class ThreadTest1 {
public static int idCounter = 0;
public class MyThread extends Thread {
private int id;
public MyThread() {
this.id = idCounter++;
}
public void run() {
// this run method represents the long-running file processing
System.out.println("I'm thread '"+this.id+"' and I'm going to sleep for 5 seconds!");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I'm thread '"+this.id+"' and I'm done sleeping!");
}
}
public void go() {
int MAX_NUM_THREADS = 10;
List<MyThread> threads = new ArrayList<MyThread>();
// this for loop represents the 200 files that need to be processed
for (int i=0; i<200; i++) {
// if we've reached the max num of threads ...
while (threads.size() == MAX_NUM_THREADS) {
// loop through the threads until we find a dead one and remove it
for (MyThread t : threads) {
if (!t.isAlive()) {
threads.remove(t);
break;
}
}
}
// add new thread
MyThread t = new MyThread();
threads.add(t);
t.start();
}
}
public static void main(String[] args) {
new ThreadTest1().go();
}
}
You can use ExecutorService to manage you threads.
And you can add while loop to thread run method to execute file processing task repeatedly.
Also you can read about BlockingQueue usage. I think it will fit perfectly to allocate new files (tasks) between threads.
I would suggest using Camel's File component if you are open to it. The component will handle all the issues with concurrency to ensure that multiple threads don't try to process the same file. The biggest challenge with making your code multi-threaded is making sure the threads don't interact. Let a framework take care of this for you.
Example:
from("file://incoming?maxMessagesPerPoll=1&idempotent=true&moveFailed=failed&move=processed&readLock=none")
.threads(10).process()
I want to start max 40 http requests each second and after 1 second, I want it to run another 40 from its own queue(like threadpooltaskexecutor's blocking queue). I am looking for an executor or thread pool implementation for this requirement.
Any recommendations?
Thx
Ali
EDIT: Fix rate is not efficient for the obvious reasons. As the queue items start one by one, the ones on the back of the queue will be just started but ones that has been started for a while may be finished.
Extra EDIT: The problem is to call only 40 request in a second, not have max 40 active. It can be 80 at other second but in 1 second there should only 40 newly created connections.
One way to do this is to use another architecture, it will make the process that much easiser.
1) Create a Thread class that implements the runnable.
2) It takes as parameters a list<>() of http requests that you want to make
3) Make the run() function loop the entire list (size 40)
4) Let the thread live for one second.
Here is a sample example:
class MyClass extends Thread
private ArrayList<...> theList;
public MyClass(ArrayList<..> theList){
this.theList = theList;
}
public void run(){
//Here, you simply want to loop for the entier list (max 40)
for(Req r: theList){
r.sendRequest()
)
}
public statc void main(String args[]){
//Create an instance of your thread:
MyClass t = new MyClass(ReqList<..>());
//Now that you have your thread, simply do the following:
while(true){
t = new MyClass( (insert your new list));
t.start();
try{
Thread.sleep(1000);
}catch(Exception e){
}
)
}
}
And there you have it
First define a class that implements Callable which will do your thread's treatment :
class MyClass implements Callable<String>
{
/**
* Consider this as a new Thread.
*/
#Override
public String call()
{
//Treatment...
return "OK"; //Return whatever the thread's result you want to be then you can access it and do the desired treatment.
}
}
Next step is to create an ExecutorService in my example, a Thread pool and throw in some tasks.
int nbThreadToStart = 40;
ExecutorService executor = Executors.newFixedThreadPool(/* Your thread pool limit */);
List<Future<String>> allTasks = new ArrayList<Future<String>>(/* Specify a number here if you want to limit your thread pool */);
for(int i = 0; i < 10; i++)//Number of iteration you want
{
for(int i = 0; i < nbThreadToStart; i++)
{
try
{
allTasks.add(executor.submit(new MyClass()));
}
catch(Exception e)
{
e.printStackTrace();
}
}
try
{
Thread.sleep(1000);
}
catch(Exception e)
{
e.printStackTrace();
}
}
executor.shutdown();
//You can then access all your thread(Tasks) and see if they terminated and even add a timeout :
try
{
for(Future<String> task : allTasks)
task.get(60, TimeUnit.SECONDS);//Timeout of 1 seconds. The get will return what you specified in the call method.
}
catch (TimeOutException te)
{
...
}
catch(InterruptedException ie)
{
...
}
catch(ExecutionException ee)
{
...
}
I'm not sure what you really want, but I think you should handle multi-threading with a thread pool specially if you're planning on receiving a lot of requests to avoid any undesired memory leak etc.
If my example is not clear enough, note that there is many other methods offered by ExexutorService,Future etc. that are very usefull when dealing with Thread.
Check this out :
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executor.html
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html
That's it for my recommandations.