I have some Java app using Spring Batch. I've got a table used as a queue which contains information on jobs that were requested by clients (as a client requests for a task to be executed, a row is added to this queue).
In one of my classes a while loop is run until someone deactivates some flag :
protected void runJobLaunchingLoop() {
while (!isTerminated()) {
try {
if (isActivated()) {
QueueEntryDTO queueEntry = dequeueJobEntry();
launchJob(queueEntry);
}
}
catch (EmptyQueueException ignored) {}
catch (Exception exception) {
logger.error("There was a problem while de-queuing a job ('" + exception.getMessage() + "').");
}
finally {
pauseProcessor();
}
}
}
The pauseProcessor() method calls Thread.sleep(). When I run this app in a Docker container it looks like the number of threads run by the application keep on increasing. The threads have the name "Timer-X" with X some integer that auto-increments.
I looked at the stack trace of one of these :
"Timer-14" - Thread t#128
java.lang.Thread.State: WAITING
at java.base#11.0.6/java.lang.Object.wait(Native Method)
- waiting on <25e60c31> (a java.util.TaskQueue)
at java.base#11.0.6/java.lang.Object.wait(Unknown Source)
at java.base#11.0.6/java.util.TimerThread.mainLoop(Unknown Source)
- locked <25e60c31> (a java.util.TaskQueue)
at java.base#11.0.6/java.util.TimerThread.run(Unknown Source)
Locked ownable synchronizers:
- None
Any idea what could be the cause of this? I'm not sure but if I don't run the app in a container but locally from IntelliJ, it seems like the problem does not occur. I'm not sure because sometimes it takes a while before thread count starts increasing.
EDIT : Some relevant code ...
protected QueueEntryDTO dequeueJobEntry() {
Collection<QueueEntryDTO> collection = getQueueService().dequeueEntry();
if (collection.isEmpty())
throw new EmptyQueueException();
return collection.iterator().next();
}
#Transactional
public Collection<QueueEntryDTO> dequeueEntry() {
Optional<QueueEntry> optionalEntry = this.queueEntryDAO.findTopByStatusCode(QueueStatusEnum.WAITING.getStatusCode());
if (optionalEntry.isPresent()) {
QueueEntry entry = (QueueEntry)optionalEntry.get();
QueueEntry updatedEntry = this.saveEntryStatus(entry, QueueStatusEnum.PROCESSING, (String)null);
return Collections.singleton(this.queueEntryDTOMapper.toDTO(updatedEntry));
} else {
return new ArrayList();
}
}
private void pauseProcessor() {
try {
Long sleepDuration = generalProperties.getQueueProcessingSleepDuration();
sleepDuration = Objects.requireNonNullElseGet(
sleepDuration,
() -> Double.valueOf(Math.pow(2.0, getRetries()) * 1000.0).longValue());
Thread.sleep(sleepDuration);
if (getRetries() < 4)
setRetries(getRetries() + 1);
}
catch (Exception ignored) {
logger.warn("Failed to pause job queue processor.");
}
}
It seems like this was caused by a bug that was resolved in a more recent version of DB2 than I was using.
Applications are getting large number of timer threads when API
timerLevelforQueryTimeout value is not set explicitly in an
application using JCC driver version 11.5 GA (JCC 4.26.14) or
later.
This issue is fixed in 11.5 M4 FP0(JCC 4.27.25).
I updated the version to a newer one (11.5.6) in my POM file, but this didn't fix the issue. Turns out my K8s pod was still using 11.5.0 and Maven acted weird. I then applied this technique (using dependencyManagement in the POM file) and the newer version was loaded.
I am using the CloseableHttpClient with the PoolingHttpClientConnectionManager. I am using this client to make POST requests to a single URL. PoolingHttpClientConnectionManager is set with a "max total" of 3 connections, TTL set to 5 seconds, connection/socket timeout 5 secs. Here is what I see (note that the requests are made sequentially not concurrently):
POST request #1: 1 connection in the pool
POST request #2: 2 connections in the pool
POST request #3: 3 connections in the pool
POST request #4: last used connection is closed, a new connection is created
I'm not sure why the last used connection is closed and a new connection is established with the fourth request. Why doesn't the connection manager reuse of the existing connections?
Here is what I see in the log:
2020-05-20 22:34:12 DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Connection request: [route: {s}->https://xxxxx.com:443][total kept alive: 2; total allocated: 2 of 3]
2020-05-20 22:34:12 DEBUG o.a.h.i.c.LoggingManagedHttpClientConnection - http-outgoing-3: Close connection
I traced it down to the following code in HttpComponent's AbstractConnPool.java (httpcore-4.4.4.jar) file (function getPoolEntryBlocking):
int maxPerRoute = this.getMax(route);
int excess = Math.max(0, pool.getAllocatedCount() + 1 - maxPerRoute);
int totalUsed;
if (excess > 0) {
for(totalUsed = 0; totalUsed < excess; ++totalUsed) {
E lastUsed = pool.getLastUsed();
if (lastUsed == null) {
break;
}
lastUsed.close();
this.available.remove(lastUsed);
pool.remove(lastUsed);
}
}
Can someone explain why it needs to close the connection (lastUsed.close())?
The code below is running locally but not on the cluster. It hangs on GroupReduceFunction and do not terminates even after hours (it takes for large data ~ 9 minutes to compute locally). The last message in the log:
GroupReduce (GroupReduce at main(MyClass.java:80)) (1/1) (...) switched from DEPLOYING to RUNNING.
The code fragment:
DataSet<MyData1> myData1 = env.createInput(new UserDefinedFunctions.MyData1Set());
DataSet<MyData2> myData2 = DataSetUtils.sampleWithSize(myData1, false, 8, Long.MAX_VALUE)
.reduceGroup(new GroupReduceFunction<MyData1, MyData2>() {
#Override
public void reduce(Iterable<MyData1> itrbl, Collector<MyData2> clctr) throws Exception {
int id = 0;
for (MyData1 myData1 : itrbl) {
clctr.collect(new MyData2(id++, myData1));
}
}
});
Any ideas how I could run this segment in parallel? Thanks in advance!
My app gets traffic updates from an API (this works) and returns a JSON array, which i'm then taking each element of in a while loop (JSONobject) and attempting to update a TextView with each result every 5 seconds.
However, my script is waiting 15 seconds and then updating to the last value. I've done some research and it says to use asynctask, which I have done, but it has not made a difference.
I've added System.out.println(thestring_to_update_to), and this is working as I would like my app to do (changing every 5 seconds).
The following is in a try/catch block :
JSONArray TrafficInformation = new JSONArray(response);
int TrafficEvents = TrafficInformation.length();
int TrafficEvent = 0;
JSONObject CurrentEvent = new JSONObject();
do{
CurrentEvent = new JSONObject(TrafficInformation.getString(TrafficEvent));
TextView affected_route = (TextView)findViewById(R.id.disrupted_route);
try {
Object[] passTo = new Object[1];
passTo[0] = CurrentEvent.getString("9");
System.out.println(passTo[0]);
new tasker().doInBackground(passTo);
TrafficEvent++;
Thread.sleep(5000);
} catch (Exception e){
Toast.makeText(LiftShare.this, "There was an error with getting traffic info.", Toast.LENGTH_LONG).show();
}
} while (TrafficEvent < TrafficEvents);
I also have this public class
public class tasker extends AsyncTask {
#Override
protected Object[] doInBackground(Object[] Objects) {
TextView affected_route = (TextView)findViewById(R.id.disrupted_route);
affected_route.setText(Objects[0].toString());
return null;
};
}
this is the JSONArray that goes in to the code (It is formatted correctly)
Array
(
[0] => {"1":"Congestion","2":"Minor Disruption - up to 15 minutes delay","3":"Location : The M3 eastbound exit slip at junction J9 . \nReason : Congestion. \nStatus : Currently Active. \nReturn To Normal : Normal traffic conditions are expected between 11:30 and 11:45 on 25 January 2018. \nDelay : There are currently delays of 10 minutes against expected traffic. \n","7":"M3 J9 eastbound exit | Eastbound | Congestion","9":"M3","10":"South East","11":"Hampshire","14":"2018-01-25T11:22:38+00:00"}
[1] => {"1":"Overturned Vehicle","2":"Severe Disruption - in excess of 3 hours delay or road closure","3":"Location : The M3 westbound between junctions J8 and J9 . \nReason : Clearing the scene of an overturned vehicle. \nStatus : Currently Active. \nTime To Clear : The event is expected to clear between 14:45 and 15:00 on 25 January 2018. \nReturn To Normal : Normal traffic conditions are expected between 14:45 and 15:00 on 25 January 2018. \nLanes Closed : All lanes are closed. \nPrevious Reason : Following an earlier accident. \n","7":"M3 westbound between J8 and J9 | Westbound | Overturned Vehicle","9":"M3","10":"South East","11":"Hampshire","14":"2018-01-25T06:51:12+00:00"}
[2] => {"1":"Congestion","2":"Moderate Disruption - between 15 minutes and 3 hours delay","3":"Location : The A34 southbound between the A272 and the junction with the M3 . \nReason : Congestion. \nStatus : Currently Active. \nReturn To Normal : Normal traffic conditions are expected between 12:45 and 13:00 on 25 January 2018. \nDelay : There are currently delays of 40 minutes against expected traffic. \n","7":"A34 southbound within the A272 junction | Southbound | Congestion","9":"A34","10":"South East","11":"Hampshire","14":"2018-01-25T07:48:23+00:00"}
)
How can I get the textview to update to the new value every 5 seconds?
You have to use
new tasker().execute(passTo);
to start asynctask as a thread otherwise, with current implementation, it will just act as a normal method call
Note: you cannot update UI from background thread i.e. inside doInBackground, instead override onPostExecute which runs on UI thread
#Override
protected Object[] doInBackground(Object[] Objects) {
TextView affected_route = (TextView)findViewById(R.id.disrupted_route);
//affected_route.setText(Objects[0].toString()); crash, instead do this in onPostExecute
return null;
};
Update : you can use postDelayed with delay to update UI after some interval
int i = 0;
affected_route.postDelayed(new Runnable() {
public void run() {
textView.setText(yourText);
}
},i+=5000);
AsyncTask seems like a overkill for your requirement as you are not really doing any work in the background. You could schedule the text to be updated after a time period using a Handler (from android.os) like this:
Handler handler = new Handler(Looper.getMainLooper());
Runnable textUpdater = new Runnable() {
#Override
public void run() {
// this needs to execute in the UI thread
affected_route.setText(lastUpdate);
}
};
String lastUpdate = "Store your last update here";
void updateText(){
handler.postDelayed(textUpdater, 5000);
}
I am getting Timeout exceptions even though there is not much load on the Couchbase server.
net.spy.memcached.OperationTimeoutException: Timeout waiting for value
at net.spy.memcached.MemcachedClient.get(MemcachedClient.java:1003)
at net.spy.memcached.MemcachedClient.get(MemcachedClient.java:1018)
at com.eos.cache.CacheClient.get(CacheClient.java:280)
at com.eos.cache.GenericCacheAccessObject.get(GenericCacheAccessObject.java:55)
...
...
Caused by: net.spy.memcached.internal.CheckedOperationTimeoutException: Timed out waiting for operation - failing node: /192.168.4.12:11210
at net.spy.memcached.internal.OperationFuture.get(OperationFuture.java:157)
at net.spy.memcached.internal.GetFuture.get(GetFuture.java:62)
at net.spy.memcached.MemcachedClient.get(MemcachedClient.java:997)
...30 more
This is how I am creating the client.
List<URI> uris = new ArrayList<URI>();
String[] serverTokens = getServers().split(" ");
for (int index = 0; index < serverTokens.length; index++) {
uris.add(new URI(serverTokens[index]));
}
CouchbaseConnectionFactoryBuilder ccfb = new CouchbaseConnectionFactoryBuilder();
ccfb.setProtocol(Protocol.BINARY);
ccfb.setOpTimeout(10000); // wait up to 10 seconds for an operation to
// succeed
ccfb.setOpQueueMaxBlockTime(5000); // wait up to 5 seconds when trying
// to enqueue an operation
ccfb.setMaxReconnectDelay(1500);
CouchbaseConnectionFactory cf = ccfb.buildCouchbaseConnection(uris, bucket, "");
CouchbaseClient client = new CouchbaseClient(cf);
I am maintaining a pool of persistent clients in our web server. And we are not even touching the max conn limit which has been set to 15 only.
Pls help me guys in solving this.