I have code such that:
while(isResponseArrived)
Thread.yield();
But what I'd really like to do is something like this:
long startTime = System.currentTimeInMilliseconds();
while(isResponseArrived)
{
if(isTimeoutReached(startTime))
throw new TimeOutExcepton();
Thread.yield();
}
I'm not yet sure about throwing an exception or not (it's not important for this question), but what I'd like to know is how to make it as performant as possible, so I'm not chugging away on the processor. In other words how can I make isTimeoutReached(long startTime) as performance friendly as possible.
I tested:
for(int x=0; x<99999999; x++)
System.nanoTime();
versus
for(int x=0; x<99999999; x++)
System.currentTimeInMilliseconds();
And the difference was minimal, less than 10% in terms of time to complete
I also look at using Thread.sleep(), but I really want the user to be notified as quickly as possible if there's an update and the processor is just waiting. Thread.yield() doesn't get the processor churning, it's just a NOP, giving anyone else processor priority, until it's good to go.
Anyways, what's the best way to test for a timeout without throttling the CPU? Is this the right method?
I think it would be more efficient to use wait / notify
boolean arrived;
public synchronized void waitForResponse(long timeout) throws InterruptedException, TimeoutException {
long t0 = System.currentTimeMillis() + timeout;
while (!arrived) {
long delay = System.currentTimeMillis() - t0;
if (delay < 0) {
throw new TimeoutException();
}
wait(delay);
}
}
public synchronized void responseArrived() {
arrived = true;
notifyAll();
}
In my experience timeout are arbitarily chosen as as such as not time critical. If I choose a timeout of 1000 ms and it takes 1001 ms instead the impact should be trivial. For implementing timesout I suggest making the implementation as simple as possible.
You can implement Timeouts with a ScheduledExecutorService e.g.
final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
public void addTimeoutForTask(final Future future, int timeOutMS) {
ses.schedule(new Runnable() {
#Override
public void run() {
future.cancel(true);
}
}, timeOutMS, TimeUnit.MILLISECONDS);
}
If you are performing some non-blocking operation and you want this to timeout you can do.
interface TimedPoller {
public void poll();
/**
* #return is it now closed.
*/
public boolean checkTimeout(long nowNS);
}
private final Set<TimedPoller> timedPollers = new LinkedHashSet<>();
private volatile TimedPoller[] timedPollersArray = {};
public void add(TimedPoller timedPoller) {
synchronized (timedPollers) {
long nowNS = System.nanoTime();
if (!timedPoller.checkTimeout(nowNS) && timedPollers.add(timedPoller))
timedPollersArray = timedPollers.toArray(new TimedPoller[timedPollers.size());
}
}
public void remove(TimedPoller timedPoller) {
synchronized (timedPollers) {
if (timedPollers.remove(timedPoller))
timedPollersArray = timedPollers.toArray(new TimedPoller[timedPollers.size());
}
}
private volatile boolean running = true;
public void run() {
while (running) {
// check the timeout for every 1000 polls.
for (int i = 0; i < 1000; i += timedPollersArray.length) {
TimedPoller[] pollers = timedPollersArray;
for (TimedPoller poller : pollers) {
poller.poll();
}
}
long nowNS = System.nanoTime();
TimedPoller[] pollers = timedPollersArray;
for (TimedPoller poller : pollers) {
if (poller.checkTimeout(nowNS))
remove(poller);
}
}
}
Either you give up the CPU or you don't. If you give up the CPU, other threads can run but you will get a delay before you can run again. Or you don't give up the CPU which improves your response time, but another thread cannot run.
It appears you want to be able to let other things run, without the cost of giving up the CPU. This is not trivial but can give you some of the benefits of both if done correctly (or worst of both if not done efficiently)
What you can do is implement your own threading logic provided you have lots of small tasks, e.g. say you want to poll ten things you can use just one CPU.
Related
I'm new to using Java and I'm trying to learn threading, so it'd be helpful to get some pointers on this. I don't understand much about using threads, so a for-dummies type of explanation would also help a lot.
I'm working on a project where I have a function foo, and a List of strings which I would like to pass through foo. If the processing time for foo(S) goes over T milliseconds, I will stop processing foo(S), and then I would move on to foo(S+1). I have a large dataset of strings and they can take too long so I tried using threading and termination to speed things up, but I'm not sure how to terminate if processing takes too long. This is more or less what foo does:
public static foo(String s){
// use a while loop to manipulate string
// return some integer
}
After some research, I found out that ExecutorService would be a good approach, and this is the structure of what I have so far:
public static void process(List<String> l, int n) {
ExecutorService executor = Executors.newFixedThreadPool(n);
for (final String s: l) {
executor.submit(new Runnable() {
#Override
public void run() {
System.out.println(foo(s));
//interrupt this process if foo(s) takes >T
}
});
}
executor.shutdown();
}
However, if I run my code without on a small set of strings, it does not terminate nor print anything at all and I am unsure why. Is it stuck inside the for loop in foo? How do I fix that? Can I add a sleep(T) between threads to interrupt a thread that is taking too long? thanks!
It's not really possible to cancel a task exactly after a specific time. Canceling a task at a specific time (canceling in a sense that the task terminates immediately) would be dangerous, because it could leave data in an inconsistent state, without having the chance to "clear things up".
Therefore, we have interrupts to do a similar thing. You interrupt a task (or a thread), which is basically a notification for the task e.g. to stop its execution by itself. In this way, the task is able to terminate in a controlled manner and leave data in a consistent state.
In your example, it would work like so: Every processing of a string in your list would be a task. You have two ways to implement the timeout-mechanism: The task is canceled externally (using interrupts) or it cancels itself. When the task cancels itself, it periodically checks if it is running longer than a timeout, while processing the string. If the timeout is exceeded, the initial value is the result, otherwise the processed string.
In Java it would be something like this:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class Main {
static class ProcessTask implements Callable<String> {
final String initialValue;
final long timeout;
ProcessTask(String initialValue, long timeout) {
this.initialValue = initialValue;
this.timeout = timeout;
}
#Override
public String call() throws Exception {
long complexity = (long) (Math.random() * 1_000_000L);
long starttime = System.currentTimeMillis();
for (long i = 0; i < complexity; ++i) {
Math.sqrt(Math.log(i));
if (System.currentTimeMillis() - starttime > timeout) {
return initialValue;
}
}
return "new";
}
}
static void process(List<String> initialList, int parallelism, int timeout) {
ExecutorService executor = Executors.newFixedThreadPool(parallelism);
List<Future<String>> futures = new ArrayList<>();
initialList.forEach(s -> {
futures.add(executor.submit(new ProcessTask(s, timeout)));
});
for (int i = 0; i < initialList.size(); ++i) {
try {
initialList.set(i, futures.get(i).get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
public static void main(String[] args) {
List<String> myList = new ArrayList<>();
for (int i = 0; i < 1_000; ++i) {
myList.add("old");
}
process(myList, Runtime.getRuntime().availableProcessors(), 10);
myList.forEach(System.out::println);
}
}
This is a very explicit way of doing it, but you've asked for it. There are definitely ways of doing that less wordy. If you are unsure about any class here, just do a little bit of research. There is nothing crazy I've used.
What you should see is a mix of olds and news in the output, where new just indicates that the processing was finished and old that the timeout was exceeded and the corresponding task was stopped. If you see something else, play around with the timeout parameter of process.
The most important part for you to look at is the call method. There is the mechanism that stops a task after a timeout by periodically checking the runtime. You need place those checks at correct places in your processing algorithm to stop the task.
public class MyResource {
private int count = 0;
void increment() {
count++;
}
void insert() { // incrementing shared resource count
for (int i = 0; i < 100000000; i++) {
increment();
}
}
void insert1() { //incrementing shared resource count
for (int i = 0; i < 100000000; i++) {
increment();
}
}
void startThread() {
Thread t1 = new Thread(new Runnable() { //thread incrementing count using insert()
#Override
public void run() {
insert();
}
});
Thread t2 = new Thread(new Runnable() { //thread incrementing count using insert1()
#Override
public void run() {
insert1();
}
});
t1.start();
t2.start();
try {
t1.join(); //t1 and t2 race to increment count by telling current thread to wait
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void entry() {
long start = System.currentTimeMillis();
startThread(); //commenting insert(); insert1() gives output as time taken = 452(approx) 110318544 (obvious)
// insert(); insert1(); //commenting startThread() gives output as time taken = 452(approx) 200000000
long end = System.currentTimeMillis();
long time = end - start;
System.out.println("time taken = " + time);
System.out.println(count);
}
}
Program entry point is from entry() method.
1.Only using insert(); insert1(); (Normal method calling ) and commenting startThread()(which executes thread) gives me result as shown in code.
2.Now commenting insert(); insert1(); and using startThread()(which executes thread) gives me result as shown in code.
3.Now I synchronize increment() gives me output as time taken = 35738 200000000
As Above synchronizing avoids access of shared resource but on other hand it takes lot of time to process.
So what's use of this synchronizing if it decrease the performance ?
Sometimes you just want two or more things to go on at the same time. Imagine the server of a chat application or a program that updates the GUI while a long task is running to let the user know that processing is going on
You are not suppose to use synchronization to increase performance, you are suppose to use it in order to protect shared resources.
Is this a real code example? Because if you want to use threads here in order to split the work synchronize
increment()
is not the best approach...
EDIT
as described here, you can change the design of this specific code to divide the work between the 2 threads more efficiently.
i altered their example to fit your needs, but all the methods described there are good.
import java.util.*;
import java.util.concurrent.*;
import static java.util.Arrays.asList;
public class Sums {
static class Counter implements Callable<Long> {
private final long _limit;
Counter(long limit) {
_limit = limit;
}
#Override
public Long call() {
long counter = 0;
for (long i = 0; i <= _limit; i++) {
counter++
}
return counter;
}
}
public static void main(String[] args) throws Exception {
int counter = 0;
ExecutorService executor = Executors.newFixedThreadPool(2);
List <Future<Long>> results = executor.invokeAll(asList(
new Counter(500000), new Counter(500000));
));
executor.shutdown();
for (Future<Long> result : results) {
counter += result.get();
}
}
}
and if you must use synchronisation, AtomicLong will do a better job.
Performance is not the only factor. Correctness can also be very important. Here is another question that has some low level details about the keyword synchronized.
If you are looking for performance, consider using the java.util.concurrent.atomic.AtomicLong class. It has been optimized for fast, atomic access.
EDIT:
Synchonized is overkill in this use case. Synchronized would be much more useful for FileIO or NetworkIO where the calls are much longer and correctness is much more important. Here is the source code for AtomicLong. Volatile was chosen because it is much more performant for short calls that change shared memory.
Adding a synchronized keyword adds in extra java bytecode that does a lot of checking for the right state to get the lock safely. Volatile will put the data in main memory, which takes longer to access, but the CPU enforces atomic access instead of the jvm generating extra code under the hood.
Problem Statement is:-
Each thread uses unique ID between 1 and 1000 and program has to run for 60 minutes or more, So in that 60 minutes it is possible that all the ID's will get finished so I need to reuse those ID's again,
I know several ways to do it, one way is the below that I wrote by taking help from StackOverflow, but when I tried running this, what I found is that, after few minutes of run this program gets very slow and it takes lot of time to print the ID on the console. And also I get OutOfMemory Error sometimes. Is there any better way to solve this kind of problem?
class IdPool {
private final LinkedList<Integer> availableExistingIds = new LinkedList<Integer>();
public IdPool() {
for (int i = 1; i <= 1000; i++) {
availableExistingIds.add(i);
}
}
public synchronized Integer getExistingId() {
return availableExistingIds.removeFirst();
}
public synchronized void releaseExistingId(Integer id) {
availableExistingIds.add(id);
}
}
class ThreadNewTask implements Runnable {
private IdPool idPool;
public ThreadNewTask(IdPool idPool) {
this.idPool = idPool;
}
public void run() {
Integer id = idPool.getExistingId();
someMethod(id);
idPool.releaseExistingId(id);
}
private void someMethod(Integer id) {
System.out.println("Task: " +id);
}
}
public class TestingPool {
public static void main(String[] args) throws InterruptedException {
int size = 10;
int durationOfRun = 60;
IdPool idPool = new IdPool();
// create thread pool with given size
// create thread pool with given size
ExecutorService service = new ThreadPoolExecutor(size, size, 500L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());
// queue some tasks
long startTime = System.currentTimeMillis();
long endTime = startTime + (durationOfRun * 60 * 1000L);
// Running it for 60 minutes
while(System.currentTimeMillis() <= endTime) {
service.submit(new ThreadNewTask(idPool));
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
I already explained you in your previous question that your code submitted millions and millions of tasks to the executor, since it submits tasks in a loop during 60 minutes, withot waiting.
It's very unclear what your end goal is, but as is, you're filling a queue of tasks until you don't have any memory available anymore. Since you don't explain the goal of your program, it's hard to give you any solution.
But the first thing you could do is to limit the size of the task queue of your executor. This would force the main thread to block each time the queue is full.
So this seems like a pretty common use case, and maybe I'm over thinking it, but I'm having an issue with keeping centralized metrics from multiple threads. Say I have multiple worker threads all processing records and I every 1000 records I want to spit out some metric. Now I could have each thread log individual metrics, but then to get throughput numbers, but I'd have to add them up manually (and of course time boundaries won't be exact). Here's a simple examples:
public class Worker implements Runnable {
private static int count = 0;
private static long processingTime = 0;
public void run() {
while (true) {
...get record
count++;
long start = System.currentTimeMillis();
...do work
long end = System.currentTimeMillis();
processingTime += (end-start);
if (count % 1000 == 0) {
... log some metrics
processingTime = 0;
count = 0;
}
}
}
}
Hope that makes some sense. Also I know the two static variables will probably be AtomicInteger and AtomicLong . . . but maybe not. Interested in what kinds of ideas people have. I had thought about using Atomic variables and using a ReeantrantReadWriteLock - but I really don't want the metrics to stop the processing flow (i.e. the metrics should have very very minimal impact on the processing). Thanks.
Offloading the actual processing to another thread can be a good idea. The idea is to encapsulate your data and hand it off to a processing thread quickly so you minimize impact on the threads that are doing meaningful work.
There is a small handoff contention, but that cost is usually a lot smaller than any other type of synchronization that it should be a good candidate in many situations. I think M. Jessup's solution is pretty close to mine, but hopefully the following code illustrates the point clearly.
public class Worker implements Runnable {
private static final Metrics metrics = new Metrics();
public void run() {
while (true) {
...get record
long start = System.currentTimeMillis();
...do work
long end = System.currentTimeMillis();
// process the metric asynchronously
metrics.addMetric(end - start);
}
}
private static final class Metrics {
// a single "background" thread that actually handles
// processing
private final ExecutorService metricThread =
Executors.newSingleThreadExecutor();
// data (no synchronization needed)
private int count = 0;
private long processingTime = 0;
public void addMetric(final long time) {
metricThread.execute(new Runnable() {
public void run() {
count++;
processingTime += time;
if (count % 1000 == 0) {
... log some metrics
processingTime = 0;
count = 0;
}
}
});
}
}
}
I would suggest if you don't want the logging to interfere with the processing, you should have a separate log worker thread and have your processing threads simply provide some type of value object that can be handed off. In the example I choose a LinkedBlockingQueue since it has the ability to block for an insignificant amount of time using offer() and you can defer the blocking to another thread that pulls the values from a queue. You might need to have increased logic in the MetricProcessor to order data, etc depending on your requirements, but even if it is a long running operation it wont keep the VM thread scheduler from restarting the real processing threads in the mean time.
public class Worker implements Runnable {
public void run() {
while (true) {
... do some stuff
if (count % 1000 == 0) {
... log some metrics
if(MetricProcessor.getInstance().addMetrics(
new Metrics(processingTime, count, ...)) {
processingTime = 0;
count = 0;
} else {
//the call would have blocked for a more significant
//amount of time, here the results
//could be abandoned or just held and attempted again
//as a larger data set later
}
}
}
}
}
public class WorkerMetrics {
...some interesting data
public WorkerMetrics(... data){
...
}
...getter setters etc
}
public class MetricProcessor implements Runnable {
LinkedBlockingQueue metrics = new LinkedBlockingQueue();
public boolean addMetrics(WorkerMetrics m) {
return metrics.offer(m); //This may block, but not for a significant amount of time.
}
public void run() {
while(true) {
WorkMetrics m = metrics.take(); //wait here for something to come in
//the above call does all the significant blocking without
//interrupting the real processing
...do some actual logging, aggregation, etc of the metrics
}
}
}
If you depend on the state of count and the state of processingTime to be in synch then you would have to be using a Lock. For example if when ++count % 1000 == 0 is true, you want to evaluate the metrics of processingTime at THAT time.
For that case, it would make sense to use a ReentrantLock. I wouldn't use a RRWL because there isn't really an instance where a pure read is occuring. It is always a read/write set. But you would need to Lock around all of
count++
processingTime += (end-start);
if (count % 1000 == 0) {
... log some metrics
processingTime = 0;
count = 0;
}
Whether or not count++ is going to be at that location, you will need to lock around that also.
Finally if you are using a Lock, you do not need an AtomicLong and AtomicInteger. It just adds to the overhead and isn't more thread-safe.
I'd like to write a java while loop that will iterate for 15 seconds. One way I thought to do this would be to store the current system time + 15sec and then compare that to the current time in the while loop signature.
Is there a better way?
The design of this depends on what you want doing for 15s. The two most plausible cases are "do this every X for 15s" or "wait for X to happen or 15s whichever comes sooner", which will lead to very different code.
Just waiting
Thread.sleep(15000)
This doesn't iterate, but if you want to do nothing for 15s is much more efficient (it wastes less CPU on doing nothing).
Repeat some code for 15s
If you really want to loop for 15s then your solution is fine, as long as your code doesn't take too long. Something like:
long t= System.currentTimeMillis();
long end = t+15000;
while(System.currentTimeMillis() < end) {
// do something
// pause to avoid churning
Thread.sleep( xxx );
}
Wait for 15s or some other condition
If you want your code to be interrupted after exactly 15s whatever it is doing you'll need a multi-threaded solution. Look at java.util.concurrent for lots of useful objects. Most methods which lock (like wait() ) have a timeout argument. A semaphore might do exactly what you need.
As already mentioned by other posters, if you just want the thread to pause for some time use Thread.sleep().
If you want the thread to do something, but want to make it stop after a while, use something like:
class Foo implements Runnable {
private volatile boolean killed = false;
public void run() {
while (!killed) {
try { doOnce(); } catch (InterruptedException ex) { killed = true; }
}
}
public void kill() { killed = true; }
private void doOnce() throws InterruptedException { /* .. */ }
}
and from the main thread, do:
Foo foo = new Foo();
Thread thread = new Thread(foo);
thread.start();
/* when you want to stop it */
foo.kill();
thread.interrupt();
Your general approach seems fine although you may want to see if the current time is greater than the point you want to stop, otherwise, you might be running for a long time.
The alternative is to run a timer/thread that sets a flag after 15 seconds have elapsed. This flag would have to be marked as volatile otherwise your loop might not see the change occur in the value.
The choice if you care about efficiency is which is more expensive, getting the system time once per loop or accessing a volatile variable? I don't know which one is more efficient - you could benchmark it if it's really important.
For simple, maintainable code, I'd choose the timer check approach:
long endTime = System.currentTimeMillis() + 15000
while (System.currentTimeMillis() < endTime) {
//loop
}
try this:
public class SleepMessages {
public static void main(String args[]) throws InterruptedException {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
for (int i = 0; i < importantInfo.length; i++) {
//Pause for 15 seconds
Thread.sleep(15000);
//Print a message
System.out.println(importantInfo[i]);
}
}
}
more info : here
Never check for current time in a tight loop.
Otherwise somebody with a laptop can get get his/her lap burned by an overheated CPU. I heard the stories of this actually happening.
You can use AOP and a #Timeable annotation from jcabi-aspects (I'm a developer):
#Timeable(limit = 1, unit = TimeUnit.SECONDS)
String load(String resource) {
// do this check regularly:
if (Thread.currentThread.isInterrupted()) {
throw new IllegalStateException("time out");
}
// execution as normal
}
When time limit is reached your thread will get interrupted() flag set to true and it's your job to handle this situation correctly and to stop execution.
Assuming you want the loop to do something sensible, you might find it faster to check a volatile flag. Have another thread wait 15 seconds (or use a timer) and then set it.
Alternatively, if you know roughly how long the loop body will take, run it a few hundred times, say, and do the time check in an outer loop.
final long start = System.nanoTime();
do {
for (int i=0; i<200, ++i) {
...
}
} while (System.nanoTime()-start < 15L*1000L*1000L*1000L);
System.nanoTime should not get confused by system clock changes. Use of long literal numbers is important.
You might be interested in scheduling a TimerTask that stops another thread or changes the condition of your loop.
For the java.util.concurrent approach, refer to Chapter 6 of Java Concurrency in Practice (section 6.3.7 Placing time limits on tasks, page 131).
Code example: Fetching an advertisement with a time budget.
A solution similar to #Tom Hawtin without an arbitary loop size.
final long end = System.nanoTime() + 15 * 1000 * 1000 * 1000L;
int loop = 1;
do {
for (int i=0; i<loop; ++i) {
...
}
loop++;
} while (System.nanoTime() < end);
In this case the size of the inner loop will start small but grow in size if the loop is particularly quick. If it is slow enough, it might only iterate once.
Here is my suggestion and it's working good for me :)
StoppingTime = 15 ;
int loop = 1;
long StartTime = System.currentTimeMillis() / 1000 ;
for (int i=0; i<loop; ++i) {
// your code here
loop++;
if (((System.currentTimeMillis()/1000) - StartTime) > StoppingTime)
loop=0;
}
I would suggest you do this with the timer class avoiding the Thread.sleep(xxx); method.
for example:
import java.util.Timer;
import java.util.TimerTask;
public class TimerExample {
private int globalTimer = 0;
private int limitTimer = 15;
public static void main(String[] args) {
new TimerExample();
}
public TimerExample() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
globalTimer++;
// DO YOUR CODE HERE
System.out.println("running");
if (globalTimer == limitTimer) {
timer.cancel();
}
}
}, 0, 1000);
}
}
Use an object array as your local variable to pass to the thread. In your loop check to see if that variable has been changed by your thread.
NB
Its important to use an Array Of Object since a thread's run method will be able to access it even if it was a local variable.
How?
Create a new Thread
In the run method sleep(1000*15) for 15 seconds
Update your local variable.
//The thread method
public static boolean[] delay(int seconds) {
final boolean[] cont = new boolean[1];
cont[0] = true;
Thread thread = new Thread() {
#Override
public void run() {
try {
sleep(1000 * seconds);
cont[0] = false;
} catch (InterruptedException ex) {
}
}
};
thread.start();
return cont;
}
//The loop method
public void dance(){
//here we call our delay method time it for 15 seconds.
final boolean[] delay = delay(15);
for (int i = 0; i < size; i++) {
//your code here.
if (delay[0] == false) { //check if delay has been changed to false and break.
break;
}
}
}