I have groovy code snippet consisting of "For Loop". Inside for loop im checking condition and in else part Im adding Thread.sleep(300000) (5 mins of waiting).
for(int i=0; i<8;i++) {
if(i == 6){
print 'Condition True'
break;
} else {
try
{
Thread.sleep(300000)
} catch(e) {
Thread.currentThread().interrupt();
continue;
}
}
}
Case 1: After running this sample script, In the 1st iteration it is waiting for 5 mins, after that the loop is terminating itself. How can i wait for 30 mins with the intervals of 5 mins,
Case 2: If I add println 'Printing' in else part, then in 1st iteration it is waiting 5 mins after that is it waiting with 5 sec. How can i wait for 30 mins with the intervals of 5 mins.
When I ran the same code as posted in the description, the loop did not run even once because the condition is not correct (i>6). Once I fix the condition to i<6, then it is going into the else part for 4 times waiting for the time mentioned in sleep. After 4 times it stops because of break when i==4. So basically if you change the condition, it will wait for total 20min (for 5min every time). If you need to wait for total 30min and the if condition was added just to stop after 6 times then I do not see any need for the condition. You can just write as below.
for(int i in 1..6) {
println "Sleeping...$i"
try
{
Thread.sleep(300000)
} catch(e) {
Thread.currentThread().interrupt();
continue;
}
}
Related
According to the documentation, a delay suspends a coroutine but doesn't block a thread:
Delay is a special suspending function. It suspends the coroutine for a specific time. Suspending a coroutine does not block the underlying thread, but allows other coroutines to run and use the underlying thread for their code.
However when running this code:
fun main() {
println("1")
GlobalScope.launch {
doSomething()
delay(1000L)
println("3")
}
GlobalScope.launch {
delay(1000L)
println("4")
}
println("5")
}
suspend fun doSomething() {
delay(500L)
println("2")
delay(1000L)
}
the output given is:
1
5
2
4
3
According to my understanding, it should have shown 1 5 4 2 3.
That's because doSomething() is being called in the first coroutine and so the delay is more as compared to the second coroutine and the second coroutine is called asynchronously. Where is my misunderstanding?
Also with this piece of code, both the values are printed together after 2 seconds:
fun main() {
GlobalScope.launch {
val value1 = doSomething1()
val value2 = doSomething2()
println(value1)
println(value2)
}
}
suspend fun doSomething1(): String {
delay(1000L)
return "This is the answer1"
}
suspend fun doSomething2(): String {
delay(1000L)
return "This is the answer2"
}
Why is this?
TL;DR
No, delays in different jobs don't affect each other.
For your first problem, clearly 1 and 5 are first and last so we can ignore those. So for the rest of them we have:
Print
Delays
Total delay
2
500
500
3
500, 1000, 1000
2500
4
1000
1000
So the order would be 2, 4, 3 which you've verified with the output.
If you want to see a bit more how the coroutines are running, we can consider what's happening with each job at roughly each time step:
Time
Job 1
Job 2
0
delay(500L)
delay(1000L)
500
print("2"); delay(1000L)
-
1000
-
print("4")
1500
delay(1000L)
-
2000
-
-
2500
print("3")
-
To address your second problem, you can just write it as one block of code:
GlobalScope.launch {
delay(1000L)
val value1 = "This is the answer1"
delay(1000L)
val value2 = "This is the answer2"
println(value1)
println(value2)
}
Clearly the print statements would run one after another. Just because there was a delay in obtaining the values, doesn't mean there is a delay between printing them. The behaviour that I think you're expecting would occur if the print statements were in the two doSomething methods.
so the delay is more as compared to the second coroutine
No, the first delay is: 500L,
and the second delay is: 1000L
The code below executes a long running function (a sleep to keep it simple), then calls back itself again using a setTimeout. I am using nodejs 5.1.0
var start_time = Math.ceil(new Date() /1000)
function sleep(delay) {
var start = new Date().getTime();
while (new Date().getTime() < start + delay);
}
function iteration(){
console.log("sleeping at :", Math.ceil(new Date()/1000 - start_time));
sleep(10000); // sleep 10 secs
console.log("waking up at:", Math.ceil(new Date()/1000 - start_time));
setTimeout(iteration, 0);
}
iteration();
At the moment where setTimeout is called node is not doing anything (eventloop empty in theory?) so I expect that callback to be executed immediately. In other terms, I expect the program to sleep immediately after it wakes up.
However here is what happens:
>iteration();
sleeping at : 0
waking up at: 10
undefined
> sleeping at : 10 //Expected: Slept immediately after waking up
waking up at: 20
sleeping at : 30 //Not expected: Slept 10 secs after waking up
waking up at: 40
sleeping at : 50 //Not expected: Slept 10 secs after waking up
waking up at: 60
sleeping at : 70 //Not expected. Slept 10 secs after waking up
waking up at: 80
sleeping at : 90 //Not expected: Slept 10 secs after waking up
waking up at: 100
sleeping at : 110 //Not expected: Slept 10 secs after waking up
As you can see, the program sleeps immediately after it wakes up the first time (which is what I expect), but not after that. In fact, it waits exactly another 10 seconds between waking up and sleeping.
If I use setImmediate things work fine. Any idea what I am missing?
EDIT:
Notes:
1- In my real code, I have a complex long algorithm and not a simple sleep function. The code above just reproduces the problem in a simpler use case.
That means I can't use setTimeout(iteraton, 10000)
2- The reason why I use setTimeout with a delay of 0 is because my code blocks nodejs for so long that other smaller tasks get delayed. By doing a setTimeout, nodejs gets backs to the event loop to execute those small tasks before continuing to work on my main long running code
3- I completely understand that setInterval(function, 0) will run as soon as possible and not immediately after, however that does not explain why it runs with 10 seconds delay given that nodejs is not doing anything else
4- My code in Chrome runs without any problems. Nodejs bug?
First look at the node.js documenation:
It is important to note that your callback will probably not be called
in exactly delay milliseconds - Node.js makes no guarantees about the
exact timing of when the callback will fire, nor of the ordering
things will fire in. The callback will be called as close as possible
to the time specified.
To make your function more async you could make something like:
function iteration(callback){
console.log("sleeping at :", Math.ceil(new Date()/1000));
sleep(10000); // sleep 10 secs
console.log("waking up at:", Math.ceil(new Date()/1000));
return setTimeout(callback(iteration), 0);
}
iteration(iteration);
Next problem is your sleep function. You have a while loop blocking all your node.js processes to make something the setTimeout function of node.js does for you.
function sleep(delay) {
var start = new Date().getTime();
while (new Date().getTime() < start + delay);
}
That what happens now is that your sleep function is blocking the process. It is not only happening when you call the function directly it is also happening, when the scope of the function is initialised after the async call of setTimeout, by node.js.
And that is not a bug. It has to be like that, because inside your while loop could be something your iteration functions has to know. Specially when it is called after a setTimeout. So first the sleep function is checked and as soon as possible the function is called.
Edited answer after question change
is there any diffrence between in these approach?
val upload = for {
done <- Future {
println("uploadingStart")
uploadInAmazonS3 //take 10 to 12 sec
println("uploaded")
}
}yield done
println("uploadingStart")
val upload = for {
done <- Future {
uploadInAmazonS3 //take 10 to 12 sec
}
}yield done
println("uploadingStart")
i wanna know in terms of thread Blocking?
does thread is blocked here, while executing these three lines
println("uploadingStart")
uploadInAmazonS3 //take 10 to 12 sec
println("uploaded")
and in another it is not blocking thread it is so?
or thread are same busy in both cases?
The code within future will be executed by some thread from the executionContext(thread pool)
Yes, the thread which executes this part
println("uploadingStart")
uploadInAmazonS3 //take 10 to 12 sec
println("uploaded")
will be blocked, but not the calling thread(main thread).
In the second case both the println statements are executed by the main thread. Since the main thread simply proceeds after creating the future, the println statements are executed without any delay
The difference is that in former code, println are executed when the future is really performed, whereas in the second one println are runed when the future is declared (prepared, but not yet executed).
This code will check if three buttons in a row have the same text. If it does, it will change color to green on those buttons and change int counter to 9. When it is past this piece of code, it will reset all buttons their original state because counter == 9.
Problem is, it will sleep before it makes the buttons green. Why is that?
int counter = 0;
private void winCheck(String sign)
{
if (jButton1.getText().equals(sign))
{
if (jButton2.getText().equals(sign))
{
if (jButton3.getText().equals(sign))
{
jButton1.setBackground(Color.GREEN);
jButton2.setBackground(Color.GREEN);
jButton3.setBackground(Color.GREEN);
counter = 9;
}
try {
Thread.sleep(1000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
}
// This last part to show what I mean with reset.
counter++;
if (counter == 10)
{
jButton1.setBackground(null);
jButton1.setText(" ");
counter = 0;
}
Answer by Kirill Shlenskiy (please upvote his comments):
Problem is, it will sleep before it makes the buttons green" - that is unlikely to be true. Step through your code - I bet that the button background colour value will be exactly what you expect it to be right after you set it (and before you hit Thread.sleep). You just can't see the update because your UI thread is busy waiting on the blocking Thread.sleep call to finish and not pumping. You either need an asynchronous alternative to sleep (timer for example) or a way to force the UI element to redraw immediately. – Kirill Shlenskiy Jul 10 at 13:38
I set the colour to be green but it is not drawn before I put the thread to sleep? – uranibaba Jul 11 at 8:10
#uranibaba, correct. And that's by design. The UI thread redraws the UI when it has nothing else to do. Thread.sleep does not defer the rest of the method - it blocks the thread so that it can't do anything else (i.e. redraw the UI) until the synchronous work is complete. – Kirill Shlenskiy Jul 11 at 10:43
Background:
In reading how to multithread my perl script, I read (from http://perldoc.perl.org/threads.html#BUGS-AND-LIMITATIONS)
On most systems, frequent and continual creation and destruction of
threads can lead to ever-increasing growth in the memory footprint of
the Perl interpreter. While it is simple to just launch threads and
then ->join() or ->detach() them, for long-lived applications, it is
better to maintain a pool of threads, and to reuse them for the work
needed, using queues to notify threads of pending work.
My script will be long-lived; it's an PKI LDAP directory monitoring daemon that will always be running. The enterprise monitoring solution will generate an alarm if it stops running for any reason. My script will check that I can reach another PKI LDAP directory, as well as validate revocation lists on both.
Problem: Everything I can find on google shows passing variables (e.g. scalars) to the thread queue rather than the subroutine itself... I think I'm just not understanding how to implement a thread queue properly compared to how you implement a thread (without queues).
Question 1: How can I "maintain a pool of threads" to avoid the perl interpreter from slowly eating up more and more memory?
Question 2: (Unrelated but while I have this code posted) Is there a safe amount of sleep at the end of the main program so that I don't start a thread more than once in a minute? 60 seems obvious but could that ever cause it to run more than once if the loop is fast, or perhaps miss a minute because of processing time or something?
Thanks in advance!
#!/usr/bin/perl
use feature ":5.10";
use warnings;
use strict;
use threads;
use Proc::Daemon;
#
### Global Variables
use constant false => 0;
use constant true => 1;
my $app = $0;
my $continue = true;
$SIG{TERM} = sub { $continue = false };
# Directory Server Agent (DSA) info
my #ListOfDSAs = (
{ name => "Myself (inbound)",
host => "ldap.myco.ca",
base => "ou=mydir,o=myco,c=ca",
},
{ name => "Company 2",
host => "ldap.comp2.ca",
base => "ou=their-dir,o=comp2,c=ca",
}
);
#
### Subroutines
sub checkConnections
{ # runs every 5 minutes
my (#DSAs, $logfile) = #_;
# Code to ldapsearch
threads->detach();
}
sub validateRevocationLists
{ # runs every hour on minute xx:55
my (#DSAs, $logfile) = #_;
# Code to validate CRLs haven't expired, etc
threads->detach();
}
#
### Main program
Proc::Daemon::Init;
while ($continue)
{
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
# Question 1: Queues??
if ($min % 5 == 0 || $min == 0)
{ threads->create(&checkConnections, #ListOfDSAs, "/var/connect.log"); }
if ($min % 55 == 0)
{ threads->create(&validateRevocationLists, #ListOfDSAs, "/var/RLs.log"); }
sleep 60; # Question 2: Safer/better way to prevent multiple threads being started for same check in one matching minute?
}
# TERM RECEIVED
exit 0;
__END__
use threads;
use Thread::Queue 3.01 qw( );
my $check_conn_q = Thread::Queue->new();
my $validate_revoke_q = Thread::Queue->new();
my #threads;
push #threads, async {
while (my $job = $check_conn_q->dequeue()) {
check_conn(#$job);
}
};
push #threads, async {
while (my $job = $validate_revoke_q->dequeue()) {
validate_revoke(#$job);
}
};
while ($continue) {
my ($S,$M,$H,$m,$d,$Y) = localtime; $m+=1; $Y+=1900;
$check_conn_q->enqueue([ #ListOfDSAs, "/var/connect.log" ])
if $M % 5 == 0;
$validate_revoke_q->enqueue([ #ListOfDSAs, "/var/RLs.log" ])
if $M == 55;
sleep 30;
}
$check_conn_q->end();
$validate_revoke_q->end();
$_->join for #threads;
I'm not sure parallelisation is needed here. If it's not, you could simply use
use List::Util qw( min );
sub sleep_until {
my ($until) = #_;
my $time = time;
return if $time >= $until;
sleep($until - $time);
}
my $next_check_conn = my $next_validate_revoke = time;
while ($continue) {
sleep_until min $next_check_conn, $next_validate_revoke;
last if !$continue;
my $time = time;
if ($time >= $next_check_conn) {
check_conn(#ListOfDSAs, "/var/connect.log");
$next_check_conn = time + 5*60;
}
if ($time >= $next_validate_revoke) {
validate_revoke(#ListOfDSAs, "/var/RLs.log");
$next_validate_revoke = time + 60*60;
}
}
I would recommend just running the checks one at a time, as there does not appear to be a compelling reason to use threads here, and you don't want to add unnecessary complexity to a program that will be running all the time.
If you do want to learn how use a thread pool, there are examples included with the threads module. There is also a Thread::Pool module that may be useful.
As for ensuring you don't repeat the checks in the same minute, you are correct that sleeping for 60 seconds will be inadequate. No matter what value you choose to sleep, you will have edge cases in which it fails: either it will be slightly shorter than a minute, and you will occasionally have two checks in the same minute, or it will be slightly longer than a minute, and you will occasionally miss a check altogether.
Instead, use a variable to remember when the task was last done. You can then use a shorter sleep time without worrying about multiple checks per minute.
my $last_task_time = -1;
while ($continue)
{
my $min = (localtime(time))[1];
if ($last_task_time != $min &&
($min % 5 == 0 || $min > ($last_task_time+5)%60))
{
#Check connections here.
if ($min == 55 || ($last_task_time < 55 && $min > 55))
{
#Validate revocation lists here.
}
$last_task_time = $min;
}
else
{
sleep 55; #Ensures there is at least one check per minute.
}
}
Update: I fixed the code so that it will recover if the last task ran too long. This would be fine if it occasionally takes a long time. If the tasks are frequently taking longer than five minutes, though, you need a different solution (threads would probably make sense in that case).