More efficient way for pausing loop wanted
The tools available are:
wait
/notify
- we are all trying to get away from this archaic system.
Semaphore
s - once your thread has grabbed it you hold it until release so grabbing it again does not block. This means you cannot pause from within your own thread.
CyclicBarrier
- Must be created anew each time it is used.
ReadWriteLock
- My favorite. You can have as many threads pausing you as you like and you will only resume when all of them have called resume
. You can even pause yourself if you wish.
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* PauseableThread is a Thread with pause/resume and cancel methods.
*
* The meat of the process must implement `step`.
*
* You can either extend this and implement `step` or use the factory.
*
* Note that I cannot extend Thread because my resume will clash with Thread's deprecated one.
*
* Usage: Either write a `Stepper` and run it in a `PausableThread` or extend `PausableThread` and call `blockIfPaused()` at appropriate points.
*/
public abstract class PauseableThread implements Runnable {
// The lock.
// We'll hold a read lock on it to pause the thread.
// The thread will momentarily grab a write lock on it to pause.
// This way you can have multiple pausers using normal locks.
private final ReadWriteLock pause = new ReentrantReadWriteLock();
// Flag to cancel the wholeprocess.
private volatile boolean cancelled = false;
// The exception that caused it to finish.
private Exception thrown = null;
@Override
// The core run mechanism.
public void run() {
try {
while (!cancelled) {
// Block here if we're paused.
blockIfPaused();
// Do my work.
step();
}
} catch (Exception ex) {
// Just fall out when exception is thrown.
thrown = ex;
}
}
// Block if pause has been called without a matching resume.
private void blockIfPaused() throws InterruptedException {
try {
// Grab a write lock. Will block if a read lock has been taken.
pause.writeLock().lockInterruptibly();
} finally {
// Release the lock immediately to avoid blocking when pause is called.
pause.writeLock().unlock();
}
}
// Pause the work. NB: MUST be balanced by a resume.
public void pause() {
// We can wait for a lock here.
pause.readLock().lock();
}
// Resume the work. NB: MUST be balanced by a pause.
public void resume() {
// Release the lock.
pause.readLock().unlock();
}
// Stop.
public void cancel() {
// Stop everything.
cancelled = true;
}
// start - like a thread.
public void start() {
// Wrap it in a thread.
new Thread(this).start();
}
// Get the exceptuion that was thrown to stop the thread or null if the thread was cancelled.
public Exception getThrown() {
return thrown;
}
// Create this method to do stuff.
// Calls to this method will stop when pause is called.
// Any thrown exception stops the whole process.
public abstract void step() throws Exception;
// Factory to wrap a Stepper in a PauseableThread
public static PauseableThread make(Stepper stepper) {
StepperThread pauseableStepper = new StepperThread(stepper);
// That's the thread they can pause/resume.
return pauseableStepper;
}
// One of these must be used.
public interface Stepper {
// A Stepper has a step method.
// Any exception thrown causes the enclosing thread to stop.
public void step() throws Exception;
}
// Holder for a Stepper.
private static class StepperThread extends PauseableThread {
private final Stepper stepper;
StepperThread(Stepper stepper) {
this.stepper = stepper;
}
@Override
public void step() throws Exception {
stepper.step();
}
}
// My test counter.
static int n = 0;
// Test/demo.
public static void main(String[] args) throws InterruptedException {
try {
// Simple stepper that just increments n.
Stepper s = new Stepper() {
@Override
public void step() throws Exception {
n += 1;
Thread.sleep(10);
}
};
PauseableThread t = PauseableThread.make(s);
// Start it up.
t.start();
Thread.sleep(1000);
t.pause();
System.out.println("Paused: " + n);
Thread.sleep(1000);
System.out.println("Resuminng: " + n);
t.resume();
Thread.sleep(1000);
t.cancel();
} catch (Exception e) {
}
}
}
Edit: Code modified to be of more general use.
What is the fastest way to pause execution in c++
When you ask your thread to sleep, it is unscheduled by the operating system, and rescheduling it takes some time. If you want to pause for a very small amount of time, use _mm_pause()
. You may want to do it a fixed number of times based on your own measurements of how long it takes on your system. Intel says it takes 140 cycles on Skylake (it took much less time on older CPUs): https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_pause&expand=5146
If the amount of time you want to sleep is small but you care about how much actual time has passed, you can check the time in a loop and call _mm_pause()
once per loop. About 70 ns for clock_gettime()
plus 40 ns for _mm_pause()
should give you a resolution somewhere around 120 ns on Skylake.
In either case, you will not be explicitly releasing the CPU core to be used by other processes, and the OS may unschedule your thread if there are other threads waiting to run on the same core. So you'll need to set your CPU affinity such that nothing else can run on the same core. For details see https://www.suse.com/support/kb/doc/?id=000017747
See also: https://software.intel.com/content/www/us/en/develop/articles/benefitting-power-and-performance-sleep-loops.html
How to create pause or delay in FOR loop?
I tried all one, but I think this code is better one, it is very simple code.
var s = document.getElementById("div1");
var i = 0;
setInterval(function () {s.innerHTML = s.innerHTML + i.toString(); i++;}, 2000);
Best Method to pause a Thread?
In the FIRST case, when i use Thread.sleep inside loop the Netbeans IDE issues warning not to use Thread.sleep inside loop. Why is that?
I guess because Netbeans thinks that it won't be testing the loop condition and the code will pause unnecessarily.
In the SECOND case, when i use infinite empty while loop, is that a performance overhead?
Uh yes. Spinning a thread will take a CPU and be a performance sink.
Which method(mentioned above or otherwise) should i prefer to pause the action being performed by the Thread according to the users choice?
Neither? I would use a volatile boolean pauseFlag
for testing if the thread should pause, combined with wait/notify to unpause it. Or you can use an AtomicBoolean
which wraps a volatile boolean
but is also an object we can synchronize on. Maybe something like:
// using `AtomicBoolean` which wraps a `volatile boolean` but is const object
// NOTE: we _can't_ synchronized on Boolean, needs to be constant object reference
private final AtomicBoolean pauseFlag = new AtomicBoolean(false);
...
while (!Thread.currentThread().isInterrupted()) {
if (pauseFlag.get()) {
synchronized (pauseFlag) {
// we are in a while loop here to protect against spurious interrupts
while (pauseFlag.get())) {
try {
pauseFlag.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// we should probably quit if we are interrupted?
return;
}
}
}
}
...
}
...
public void pause() {
pauseFlag.set(true);
}
...
public void resume() {
pauseFlag.set(false);
synchronized (pauseFlag) {
pauseFlag.notify();
}
}
I guess if I were forced to pick from one of the two, I would pick the sleep(...)
loop. Even sleep(1)
is significantly better than a spin. Do you really need to un-pause quicker than ~1ms? But the wait/notify is the most efficient.
Because it has nothing to do with synchronization, i do not want to use wait/notify.
As mentioned by @Jon, some sort of synchronization is necessary here since you are trying to communicate between two threads. Certainly you need to have memory synchronization otherwise any updates to pauseFlag
will not be guaranteed to be shared between threads. This is handled by the volatile
primitive on pauseFlag
. By using wait/notify (which needs synchronized
) your code can be much more efficient about the wakeup.
Pause a for loop
This is untested, but hopefully you will get the idea. Truthfully, this is something you probably should be handling on the server-side, or doing once and storing the output in the code.
var $arr = ["","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2","3","4","5","6","7","8","9"],
len = $arr.length,
l = 0,
paused = false,
writer = '',
pauseAt = 2000;
$("body").delay(1000).show(0, function(){
function killForTwoSeconds(){ //function to timeout loop
paused = true; //set to true to kill loop
$('body').append(writer); //write to body only on pause (fewer writes to dom = faster script)
setTimeout(function(){ // wait for 2 seconds
paused = false;
loopIt(); // re-run loop
},2000);
}
function loopIt(){
$.each($arr, function(index, val){
for(var i = l; i < len; i++){
for(var j = l; j < len; j++){ //loops now start at l instead of 0 so when loop restarts it restarts at the right place
for(var k = l; k < len; k++){
if(l % pauseAt === 0){ // if l is divisible by 2000 kill
killForTwoSeconds();
}
if(!paused){ //if not paused add item to writer
thing = val+i+j+k;
l++;
$("#loading").text(l+"/15752961");
console.log(l+"/15752961");
writer = "<div>"+thing+"</div><br />";
}else if(index === len-1 && k === len-1){
$('body').append(writer); //final write
}else{
return false; // if paused return false
}
}
}
}
});
}
});
Related Topics
Background Timer Task in Jsp/Servlet Web Application
How to Use an Arraylist as a Prepared Statement Parameter
How to Cast a Double to an Int in Java by Rounding It Down
Capture and Log the Response Body
How to Limit the Number of Characters in Jtextfield
Regex Look-Behind Without Obvious Maximum Length in Java
Mapping Manytomany with Composite Primary Key and Annotation:
Preventing System.Exit() from API
Java: Why Do You Need to Specify an 'F' in a Float Literal
Why Is Accessing Textview of a Fragment Inside Activity Throwing an Error
Android Recyclerview Scrolling Performance
Android Layout with Listview and Buttons
Which Programming Languages How to Use on Android Dalvik