rescheduling created thread and stop it after fixed delay - java

I am facing one problem regarding rescheduling existing thread.Basically I want to create a new thread with some identifier in a function call and stop it after some specified period of time lets say 5 min.now two case will happen
if same function called again with same identifier within 5 min in that case thread have to reschedule its stop time again for 5 more min from current time.
if same function called again with same identifier after 5 min in that case new thread will create which will stop after 5 min.
How can I implement this?

This is close to being too broad, but here is a simple recipe how to approach such problems:
you create a holder for a timestamp which can be read and written in a thread-safe manner
when that new thread starts, it simply writes the current time into that holder
when the function is called while the thread is still running, that "other" code simply updates the timestamp to the current time
that thread should be checking the timestamp regularly - and when the thread finds "now >= timestamp + 5 min) - you know that the 5 minutes are over and the thread can stop.

i got my answer.what i have done is basically created a map which can store string as key and ScheduledFuture object as value. i used executor.schedule() method to create thread with delay of 5 min. within update method thread will be checked in map whether it exist or not. And if not available in that case method will create new thread with 5 min of delay and add it to betamap object . if update method called within 5 minutes with same thread name in that case thread will be canceled by calling t.cancel(false) and create a new thread with 5 min of delay and store it in betamap. After 5 minutes run method will be called and thread will stop automatically.but in run method i need to delete current executing thread from map.
I don't know the way i explained is understood by you guys or not but i will put code below which may be helpful to understand.
code what i have done
public class BetaUserServiceImpl{
public static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(15);
static ScheduledFuture<?> t,t1;
public static ConcurrentHashMap<String, ScheduledFuture<?>> betaMap = new ConcurrentHashMap<>();
int timeDelay = 5;
public void update(String threadname)
{
synchronized (betaMap) {
if (betaMap.containsKey(threadname))
{
t = betaMap.get(threadname);
t.cancel(false);
Iterator it = betaMap.entrySet().iterator();
while (it.hasNext())
{
Entry item = (Entry) it.next();
if(item.getKey().equals(threadname))
{
betaMap.remove(item.getKey());
}
}
t1=executor.schedule(new BetaUserThreadSchedular("thread1"),
timeDelay,TimeUnit.SECONDS);
betaMap.put(threadname, t1);
}
else
{
t=executor.schedule(new BetaUserThreadSchedular(threadname),timeDelay,TimeUnit.SECONDS);
betaMap.put(threadname, t);
}
}
}
}
Thread class
public class BetaUserThreadSchedular implements Runnable {
private Thread thread;
private String deviceId;
public BetaUserThreadSchedular(String deviceId) {
this.deviceId = deviceId;
}
public void run() {
synchronized (BetaUserServiceImpl.betaMap) {
try {
Iterator it = BetaUserServiceImpl.betaMap.entrySet().iterator();
while (it.hasNext())
{
Entry item = (Entry) it.next();
if(item.getKey().equals(deviceId) )
{
BetaUserServiceImpl.betaMap.remove(item.getKey());
}
}
}catch (Exception e) {
logger.info(e);
}
}
}
public void start() {
thread = new Thread(this);
thread.start();
}
}

Related

Java Multithreading - Remove items from list

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..

How do I make sure a line of code runs only once for each individual thread?

I have a few threads running simultaneously, and whenever each starts, I would like each individual to get one item from the String Arraylist, and hold onto that particular unique item until it completes. What would be a good way to implement this? In the run method in a thread, I though about String uniqueItem = itemList.get(k); and k++ after getting it, but the thread will run that particular line over and over, and the next time it runs it again, it will be holding onto a different unique item. Is there a way to make each thread get one item only once, and the next gets what's available, and so on, and hold onto that one item.
ItemHolder thread = new ItemHolder();
private ArrayList<String> itemList = new ArrayList<String>(); //Contains 4 Strings (e.g. Apple, Orange, Watermelon, Pear)
int k = 0;
ExecutorService executor = Executors.newFixedThreadPool(4); //E.g. run 4 Threads
executor.execute(thread);
class ItemHolder extends Thread{
public void run(){
String uniqueItem = itemList.get(k); //Would like the first thread to grab the first index item, 0, and hold onto it until it finishes. But other thread that runs the same, I would like it to have index item, 1, and hold onto that, and the other thread to have whatever is available and so on.
k++; //This would be a problem
}
}
You should use a java.util.concurrent.BlockingQueue instead, as ArrayList is not thread safe.
Example code:
public class ItemHolderDemo {
public static void main(String[] args) {
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
queue.add("a");
queue.add("b");
Runnable thread = new ItemHolder(queue);
ExecutorService executor = Executors.newFixedThreadPool(4); //E.g. run 4 Threads
executor.execute(thread);
}
static class ItemHolder extends Thread {
BlockingQueue<String> queue;
public ItemHolder(BlockingQueue<String> queue) {
this.queue = queue;
}
public void run() {
String uniqueItem = null;
// use while loop in case there is an interruption
while (uniqueItem == null) {
try {
// use queue.poll() with break statements if you want a timed wait
uniqueItem = queue.take();
} catch (InterruptedException e) {
}
}
// got item
System.out.println(uniqueItem);
}
}
}
You are using ExecutorService. This means that you do not need to pass thread instance, but a Runnable would suffice.
Having said that, you will be creating Runnable instances, and passing them to the ExecutorService in some kind of loop. You can maintain the state of each Runnable in a local field, where you can store the index on which that Runnable instance is operating on.
You would check, if your runnable's state is not set, then set it to the element that the Runnable would operate upon. If the state is already set, then do nothing.
You want to avoid the scenario where two threads execute the get() at the same time then increment k at the same time. To achieve that, you have to ensure k is incremented atomically by each thread. You can use AtomicInteger to do just that.
private ArrayList<String> itemList = new ArrayList<String>();
AtomicInteger a = new AtomicInteger();
ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i=0; i<itemList.size(); i++) { // I assume itemList will not be modified
ItemHolder thread = new ItemHolder();
executor.execute(thread);
}
class ItemHolder extends Thread{
public void run(){
int k = a.getAndAdd(1);
String uniqueItem = itemList.get(k);
// Some lengthy processing might occur here...
}
}

My timer's thread may be cheating on him with Thread.sleep?

So essentially I am concerned that my timertask's run method is not being called after 10 minutes because I am putting the main thread to sleep for 10 seconds to avoid crazy CPU usage to just run through an empty while loop all day. Here is the code for the java main method.
private static boolean testDone = false;
public static void main(String[] args)
{
final int minutes = 10;
final StressTest test = new StressTest(someParams);
test.start();
Timer timer = new Timer();
timer.schedule(new TimerTask(){
#Override
public void run() {
testDone = true;
int completedSynths = test.stop();
System.out.println("Completed Synths: " + completedSynths);
System.out.println("Elapsed Time in Minutes: " + minutes);
System.out.println("Throughput (synths/min): " + completedSynths/minutes);
}}, minutes*60*1000);
while(!testDone)
{
System.out.println("Still not done... sleeping for 10 secs....");
Thread.sleep(10000);
}
System.exit(0);
Even crazier, the System.out in the while loop is never printing. What have I done??
EDIT: TO add pseudocode for StressTest object
public class StressTest
{
private SecureRandom random = new SecureRandom();
private volatile int completedSynths = 0;
private volatile boolean shouldStop = false;
private Thread[] threads;
/**
* Instantiate a new StressTest object.
*
* #param threadCount number of concurrent threads to be polling server
*/
public StressTest(int threadCount)
{
threads = new Thread[threadCount];
}
public void start()
{
System.out.println("Starting Stress Test....");
for(int i = 0; i < threads.length; i++)
{
Runnable synthCaller = new SynthApiCaller();
threads[i] = new Thread(null, synthCaller, "SynthThread" + i);
threads[i].run();
}
}
public int stop()
{
System.out.println("Stopping Stress Test...");
shouldStop = true;
return completedSynths;
}
private String randId()
{
return new BigInteger(130, random).toString(32);
}
private class SynthApiCaller implements Runnable
{
#Override
public void run()
{
while(!shouldStop)
{
try
{
//this class makes an HTTP request to a server and then writes result to a file
MyClass.writeFile( "someFileLoc/file.data");
completedSynths++;
Runtime.getRuntime().exec("rm -r " + fileLoc);
System.out.println("Synth # " + completedSynths);
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
System.out.println("Thread terminated...");
}
}
}
I am concerned that my timertask's run method is not being called after 10 minutes because I am putting the main thread to sleep for 10 seconds
The Thread.sleep(...) in your main thread will not affect the running of the Timer. If the timer is not running after 10 minutes then is it possible that test.stop() is blocking?
It is important to realize that if the test is started in the main-thread and then is being stopped in the Timer thread then some synchronization will be necessary. I assume the test is running in another thread. You probably will need it to be synchronized then inside of the Timer thread you would call something like:
synchronized (test) {
test.start();
}
If you are new to Java synchronization, there are some good tutorials online.
If you are wondering whether or not the timer is being called at all, I'd set a break point inside your timer task where is sets testDone = true and see if it gets there.
Here's a good tutorial of using a debugger in eclipse.
Even crazier, the System.out in the while loop is never printing. What have I done??
As #assylias mentioned, the System.out(...) in your while loop not showing up must mean that testDone is set to true. Since testDone is being updated and accessed in different threads, you need to make sure it is also volatile.
I just ran your code sample without the test.start() and stop() and it seems to work fine. The problem may be in your test code.
Still not done... sleeping for 10 secs....
Still not done... sleeping for 10 secs....
...
Completed Synths: 1
Elapsed Time in Minutes: 10
Throughput (synths/min): 0
Now that you've added more code, here are some comments:
completedSynths++; should be changed to be an AtomicInteger. ++ is not an atomic operation so even tho the field is volatile, multiple threads can overwrite each other's increment.
If you are trying to wait for the threads to complete, instead of sleeping for 10 minutes, I'd recommend calling thread[i].join() with the threads. Even better would be use an ExecutorService and use the awaitTermination(...) method.
You call shouldStop = true; and then return the completedSynths;. You may want to wait for the threads to finish or something.
I'd not pass in a null ThreadGroup to the Thread constructor. Just use the constructor without the ThreadGroup.
I suggest making testDone volatile. As it is, I don't see anything forcing changes to testDone to be visible to reads in threads other than the one making the change.

Some problems with Threads

I'm having a-bit of trouble with threads in java. Basically Im creating an array of threads and starting them. the point of the program is to simulate a race, total the time for each competitor ( i.e. each thread ) and pick the winner.
The competitor moves one space, waits ( i.e. thread sleeps for a random period of time between 5 and 6 seconds ) and then continues. The threads don't complete in the order that they started as expected.
Now for the problem. I can get the total time it takes for a thread to complete; what I want is to store all the times from the threads into a single array and be able to calculate the fastest time.
To do this should I place the array in the main.class file? Would I be right in assuming so because if it was placed in the Thread class it wouldn't work. Or should I create a third class?
I'm alittle confused :/
It's fine to declare it in the method where you invoke the threads, with a few notes:
each thread should know its index in the array. Perhaps you should pass this in constructor
then you have three options for filling the array
the array should be final, so that it can be used within anonymous classes
the array can be passed to each thread
the threads should notify a listener when they're done, which in turn will increment an array.
consider using Java 1.5 Executors framework for submitting Runnables, rather than working directly with threads.
EDIT: The solution below assumes you need the times only after all competitors have finished the race.
You can use a structure that looks like below, (inside your main class). Typically you want to add a lot of you own stuff; this is the main outline.
Note that concurrency is not an issue at all here because you get the value from the MyRunnable instance once its thread has finished running.
Note that using a separate thread for each competitor is probably not really necessary with a modified approach, but that would be a different issue.
public static void main(String[] args) {
MyRunnable[] runnables = new MyRunnable[NUM_THREADS];
Thread[] threads = new Thread[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
runnables[i] = new MyRunnable();
threads[i] = new Thread(runnables[i]);
}
// start threads
for (Thread thread : threads) {
thread.start();
}
// wait for threads
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
// ignored
}
}
// get the times you calculated for each thread
for (int i = 0; i < NUM_THREADS; i++) {
int timeSpent = runnables[i].getTimeSpent();
// do something with the time spent
}
}
static class MyRunnable implements Runnable {
private int timeSpent;
public MyRunnable(...) {
// initialize
}
public void run() {
// whatever the thread should do
// finally set the time
timeSpent = ...;
}
public int getTimeSpent() {
return timeSpent;
}
}

Java Thread synchronization - printing out numbers in right order

I'm learning how to work with threads in Java and I need some advice..
I want to print on the standard output numbers from 0..50 with the name of the thread that has done it using three threads.
I have two classes - class Counter that implements Runnable and class Main that creates and runs the threads. Counter has the variable c which is shared among the threads.
My idea was, that I increment c by 1 and then call yield() on the current thread so as the other threads would do the same. Repeat this until c reaches 50.
But it doesen't work, the numbers are printed out in wrong order. How do I fix this?
public class Counter implements Runnable {
Thread t1;
private int c = -1;
public Counter() {
}
public Counter(String name) {
t1 = new Thread(this, name);
t1.start();
}
#Override
public void run() {
while (c < 50) {
increment();
Thread.yield();
}
}
public void increment() {
if (c < 50) {
c++;
System.out.println(Thread.currentThread().getName() + ": " + c);
}
}
}
public class Main {
public static void main(String[] args) throws IllegalThreadStateException {
Counter c1 = new Counter();
Thread t1 = new Thread(c1, "Thread 1");
Thread t2 = new Thread(c1, "Thread 2");
Thread t3 = new Thread(c1, "Thread 3");
t1.start();
t2.start();
t3.start();
}
Edit: In the end I solved it this way. Thank you all who helped me with the tough start with multithreading.
import java.util.concurrent.atomic.AtomicInteger;
public class Counter2 implements Runnable {
// you could also use simple int
private AtomicInteger c = new AtomicInteger(-1);
private static final Object syncObject = new Object();
public Counter2() {
}
#Override
public void run() {
while (c.get() < 50) {
synchronized (syncObject) {
if (c.get() < 50) {
System.out.println(Thread.currentThread().getName() + ": " + c.incrementAndGet());
}
}
}
}
}
Use syncrhonized section in method increment with special static object.
private static final Object syncObj = new Object();
public void increment()
{
syncrhonized( syncObj )
{
c++;
System.out.println(c);
}
}
Or make this method synchronized via its declaration.
But it's wrong idea to store your real data in thread objects. Thread should just to manipulate with share objects but not to store them.\
And actually I don't understand why do you start thread in
Quoting from the javadoc Thread.yield(), emphasis by me:
public static void yield()
A hint to the scheduler that the
current thread is willing to yield its
current use of a processor. The
scheduler is free to ignore this
hint.
...
It is rarely appropriate to use
this method.
Make increment() synchronized in order to prevent other threads from entering the method concurrently.
In conjunction with yield() you should be able to get another thread print the next number (not always since the system might resume the thread that called yield again - see Ingo's answer - , but the order should still be the same).
synchronized increment() would mean that any thread that tries to enter that method on the same object would have to wait if another thread would have aquired the lock already by entering the method.
Yes your code won't work. Thread#yield() won't control the thread scheduler in the manner you desire. I"m curious what result you get. You'll probably get repeated numbers and some number that are slightly out of order.
You could use atomic integer which should remove all duplicates. But since the print statement is not atomic. You may still print your results out of order. So you should probably just synchronize the increment method. Also you don't really need yield so dump it.
If the purpose of the problem is to go from thread 1 to thread 2 to thread 3 back to thread 1, etc... Such that the results are
Thread 1:0
Thread 2:1
Thread 3:2
Thread 1:3
Thread 2:4
Thread 3:5
Thread 1:6
Thread 2:7
....
Then you'll need to lock the increment method and use wait and notifyAll. wait will cause other threads to halt processing until the current thread notifies them to start again.

Categories