Skip to content

Commit 9e24c73

Browse files
author
zhourenjian@gmail.com
committed
Use StringBuilder instead of StringBuffer
Refactor threads, using a new thread pool for all worker threads Support pipe switching Support overriding serializing and de-serializing in sub classes
1 parent f7200c5 commit 9e24c73

27 files changed

+1017
-757
lines changed

sources/net.sf.j2s.ajax/ajaxcore/net/sf/j2s/ajax/AClass.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ protected AClass() {
6262
* }, false, true);
6363
*/
6464
public static void load(final String clazzName, final Runnable afterLoaded) {
65-
ThreadUtils.runTask(new Runnable() {
65+
SimpleThreadHelper.runTask(new Runnable() {
6666
public void run() {
6767
try {
6868
Class<?> clz = Class.forName(clazzName);
@@ -76,6 +76,6 @@ public void run() {
7676
}
7777
if (afterLoaded != null) afterLoaded.run();
7878
}
79-
});
79+
}, "Simple Asynchronous Class Loader");
8080
}
8181
}

sources/net.sf.j2s.ajax/ajaxcore/net/sf/j2s/ajax/HttpRequest.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public static String byteArrayToBase64(byte[] a) {
6868
int numFullGroups = aLen/3;
6969
int numBytesInPartialGroup = aLen - 3*numFullGroups;
7070
int resultLen = 4*((aLen + 2)/3);
71-
StringBuffer result = new StringBuffer(resultLen);
71+
StringBuilder result = new StringBuilder(resultLen);
7272
char[] intToAlpha = intToBase64;
7373

7474
// Translate all full groups from byte array elements to Base64
@@ -266,23 +266,23 @@ public void setRequestHeader(String key, String value) {
266266
* @return String the all response header value.
267267
*/
268268
public String getAllResponseHeaders() {
269-
StringBuffer buffer = new StringBuffer();
269+
StringBuilder builder = new StringBuilder();
270270
int i = 1;
271271
while (true) {
272272
String key = connection.getHeaderFieldKey(i);
273273
if (key != null) {
274274
String value = connection.getHeaderField(i);
275-
buffer.append(key);
276-
buffer.append(": ");
277-
buffer.append(value);
278-
buffer.append("\r\n");
275+
builder.append(key);
276+
builder.append(": ");
277+
builder.append(value);
278+
builder.append("\r\n");
279279
} else {
280280
break;
281281
}
282282
i++;
283283
}
284-
buffer.append("\r\n");
285-
return buffer.toString();
284+
builder.append("\r\n");
285+
return builder.toString();
286286
}
287287
/**
288288
* Get response header with given key.
@@ -384,13 +384,13 @@ public void send() {
384384
public void send(String str) {
385385
content = str;
386386
if (asynchronous) {
387-
ThreadUtils.runTask(new Runnable() {
387+
SimpleThreadHelper.runTask(new Runnable() {
388388
public void run() {
389389
if (!toAbort) {
390390
request();
391391
}
392392
}
393-
}, "Java2Script HTTP Request", false);
393+
}, "Java2Script HTTP Request Worker");
394394
} else {
395395
request();
396396
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package net.sf.j2s.ajax;
2+
3+
public class SimpleThreadConfig {
4+
/**
5+
* Core thread number. Core threads will be kept in thread pool to
6+
* make server more responsible.
7+
*/
8+
public static int simpleCoreThreads = 20;
9+
10+
/**
11+
* Max thread number. Server will allow this number of threads at the
12+
* peak. Default to 128. If set to -1, if there is no limit.
13+
*/
14+
public static int simpleMaxThreads = 128;
15+
16+
/**
17+
* If a thread is idle for given seconds, and thread number is greater
18+
* than simpleMaxThreads, this thread will be recycled.
19+
*/
20+
public static long simpleThreadIdleSeconds = 120L;
21+
22+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package net.sf.j2s.ajax;
2+
3+
import java.util.concurrent.AbstractExecutorService;
4+
import java.util.concurrent.SynchronousQueue;
5+
import java.util.concurrent.ThreadFactory;
6+
import java.util.concurrent.ThreadPoolExecutor;
7+
import java.util.concurrent.TimeUnit;
8+
import java.util.concurrent.atomic.AtomicInteger;
9+
10+
public class SimpleThreadHelper {
11+
12+
private static class NamedThreadFactory implements ThreadFactory {
13+
final ThreadGroup group;
14+
final AtomicInteger threadNumber = new AtomicInteger(1);
15+
final String namePrefix;
16+
17+
public NamedThreadFactory(String prefix) {
18+
SecurityManager s = System.getSecurityManager();
19+
group = (s != null)? s.getThreadGroup() :
20+
Thread.currentThread().getThreadGroup();
21+
namePrefix = prefix + "-";
22+
}
23+
24+
public Thread newThread(Runnable r) {
25+
Thread t = new Thread(group, r,
26+
namePrefix + threadNumber.getAndIncrement(),
27+
0);
28+
t.setDaemon(true);
29+
if (t.getPriority() != Thread.NORM_PRIORITY)
30+
t.setPriority(Thread.NORM_PRIORITY);
31+
return t;
32+
}
33+
34+
}
35+
36+
private static AbstractExecutorService poolExecutor;
37+
38+
private static boolean poolInitialized = false;
39+
40+
public static void initializePool() {
41+
if (poolInitialized) {
42+
return;
43+
}
44+
poolInitialized = true;
45+
46+
poolExecutor = new ThreadPoolExecutor(SimpleThreadConfig.simpleCoreThreads,
47+
SimpleThreadConfig.simpleMaxThreads <= 0 ? Integer.MAX_VALUE : SimpleThreadConfig.simpleMaxThreads,
48+
SimpleThreadConfig.simpleThreadIdleSeconds, TimeUnit.SECONDS,
49+
new SynchronousQueue<Runnable>(),
50+
new NamedThreadFactory("Simple Worker"));
51+
}
52+
53+
public static void runTask(Runnable r, String name) {
54+
if (poolExecutor != null) {
55+
try {
56+
poolExecutor.execute(r);
57+
return;
58+
} catch (Throwable e) {
59+
e.printStackTrace();
60+
}
61+
}
62+
Thread thread = new Thread(r, name);
63+
thread.start();
64+
}
65+
66+
}

sources/net.sf.j2s.ajax/ajaxcore/net/sf/j2s/ajax/ThreadUtils.java

Lines changed: 0 additions & 50 deletions
This file was deleted.

sources/net.sf.j2s.ajax/ajaxpipe/net/sf/j2s/ajax/CompoundPipeRunnable.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
public class CompoundPipeRunnable extends SimplePipeRunnable {
44

55
private static String nextSessionKey() {
6-
StringBuffer keyBuffer = new StringBuffer(4);
6+
StringBuilder keyBuilder = new StringBuilder(4);
77
for (int i = 0; i < 4; i++) {
88
int hex = (int) Math.floor(Math.random() * 16);
9-
keyBuffer.append((char) (hex < 10 ? ('0' + hex) : ('a' + hex - 10)));
9+
keyBuilder.append((char) (hex < 10 ? ('0' + hex) : ('a' + hex - 10)));
1010
}
11-
return keyBuffer.toString();
11+
return keyBuilder.toString();
1212
}
1313

1414
CompoundPipeSession[] pipes;

sources/net.sf.j2s.ajax/ajaxpipe/net/sf/j2s/ajax/CompoundPipeSession.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,9 @@ public boolean deal(PipeSessionClosedEvent evt) {
170170
if (pipe != null && !pipe.isPipeLive()) {
171171
String pipeKey = this.pipeKey;
172172
pipe.pipeDestroy();
173-
SimplePipeHelper.removePipe(pipeKey);
173+
if (pipeKey != null && pipeKey.length() > 0) {
174+
SimplePipeHelper.removePipe(pipeKey);
175+
}
174176
}
175177

176178
this.pipeClosed();

sources/net.sf.j2s.ajax/ajaxpipe/net/sf/j2s/ajax/SimplePipeHelper.java

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -118,18 +118,18 @@ synchronized static String registerPipe(SimplePipeRunnable pipe) {
118118
*/
119119
@J2SIgnore
120120
static String nextPipeKey() {
121-
StringBuffer buf = new StringBuffer(SimplePipeRequest.PIPE_KEY_LENGTH);
121+
StringBuilder builder = new StringBuilder(SimplePipeRequest.PIPE_KEY_LENGTH);
122122
for (int i = 0; i < SimplePipeRequest.PIPE_KEY_LENGTH; i++) {
123123
int r = (int) Math.floor(Math.random() * 62); // 0..61, total 62 numbers
124124
if (r < 10) {
125-
buf.append((char) (r + '0'));
125+
builder.append((char) (r + '0'));
126126
} else if (r < 10 + 26) {
127-
buf.append((char) ((r - 10) + 'a'));
127+
builder.append((char) ((r - 10) + 'a'));
128128
} else {
129-
buf.append((char) ((r - 10 - 26) + 'A'));
129+
builder.append((char) ((r - 10 - 26) + 'A'));
130130
}
131131
}
132-
return buf.toString();
132+
return builder.toString();
133133
}
134134

135135
@J2SNative({
@@ -138,6 +138,7 @@ static String nextPipeKey() {
138138
public static void removePipe(String key) {
139139
if (key == null) {
140140
System.out.println("Removing pipe for null key???");
141+
new RuntimeException("Removing null pipe key").printStackTrace();
141142
return;
142143
}
143144
SimplePipeRunnable pipe = null;
@@ -294,10 +295,10 @@ static void helpClosing(SimplePipeRunnable pipe) {
294295

295296
@J2SIgnore
296297
public static String printStatistics2() {
297-
StringBuffer buffer = new StringBuffer();
298-
buffer.append("Pipe monitor<br />\r\n");
298+
StringBuilder builder = new StringBuilder();
299+
builder.append("Pipe monitor<br />\r\n");
299300
if (pipes != null) {
300-
buffer.append("Totoal pipe count: " + pipes.size() + "<br />\r\n");
301+
builder.append("Totoal pipe count: " + pipes.size() + "<br />\r\n");
301302
// buffer.append("Totoal pipe map count: " + pipeMap.size() + "<br />\r\n");
302303
Object[] keys = pipes.keySet().toArray();
303304
for (int i = 0; i < keys.length; i++) {
@@ -313,30 +314,30 @@ public static String printStatistics2() {
313314
}
314315
}
315316
if (activeCount > 2) {
316-
buffer.append(i + " Pipe (active=" + activeCount + ") " + cp.pipeKey + " status=" + cp.status + " pipeAlive=" + cp.isPipeLive() + " created=" + new Date(cp.lastSetup) + "<br />\r\n");
317+
builder.append(i + " Pipe (active=" + activeCount + ") " + cp.pipeKey + " status=" + cp.status + " pipeAlive=" + cp.isPipeLive() + " created=" + new Date(cp.lastSetup) + "<br />\r\n");
317318
}
318319
}
319320
if (list != null) {
320321
int size = list.size();
321322
if (size > 20) {
322323
if (p != null) {
323-
buffer.append(i + "::: pipe " + p.pipeKey + " size : " + size + " / " + p.pipeAlive + "<br />\r\n");
324+
builder.append(i + "::: pipe " + p.pipeKey + " size : " + size + " / " + p.pipeAlive + "<br />\r\n");
324325
} else {
325-
buffer.append("Error pipe " + key + " with size : " + size + "<br />\r\n");
326+
builder.append("Error pipe " + key + " with size : " + size + "<br />\r\n");
326327
}
327328
}
328329
}
329330
}
330331
}
331-
return buffer.toString();
332+
return builder.toString();
332333
}
333334

334335
@J2SIgnore
335336
public static String printStatistics() {
336-
StringBuffer buffer = new StringBuffer();
337-
buffer.append("Pipe monitor<br />\r\n");
337+
StringBuilder builder = new StringBuilder();
338+
builder.append("Pipe monitor<br />\r\n");
338339
if (pipes != null) {
339-
buffer.append("Totoal pipe count: " + pipes.size() + "<br />\r\n");
340+
builder.append("Totoal pipe count: " + pipes.size() + "<br />\r\n");
340341
// buffer.append("Totoal pipe map count: " + pipeMap.size() + "<br />\r\n");
341342
Object[] keys = pipes.keySet().toArray();
342343
for (int i = 0; i < keys.length; i++) {
@@ -345,27 +346,27 @@ public static String printStatistics() {
345346
List<SimpleSerializable> list = p != null ? p.pipeData : null; //pipeMap.get(key);
346347
if (p instanceof CompoundPipeRunnable) {
347348
CompoundPipeRunnable cp = (CompoundPipeRunnable) p;
348-
buffer.append(i + "Pipe " + cp.pipeKey + " status=" + cp.status + " pipeAlive=" + cp.isPipeLive() + " created=" + new Date(cp.lastSetup) + "<br />\r\n");
349+
builder.append(i + "Pipe " + cp.pipeKey + " status=" + cp.status + " pipeAlive=" + cp.isPipeLive() + " created=" + new Date(cp.lastSetup) + "<br />\r\n");
349350
for (int j = 0; j < cp.pipes.length; j++) {
350351
CompoundPipeSession ps = cp.pipes[j];
351352
if (ps != null) {
352-
buffer.append(j + " : " + ps.session + " / " + ps.isPipeLive() + " pipeAlive=" + ps.pipeAlive + "<br />\r\n");
353+
builder.append(j + " : " + ps.session + " / " + ps.isPipeLive() + " pipeAlive=" + ps.pipeAlive + "<br />\r\n");
353354
}
354355
}
355356
}
356357
if (list != null) {
357358
int size = list.size();
358359
//if (size > 5) {
359360
if (p != null) {
360-
buffer.append("::: pipe " + p.pipeKey + " size : " + size + " / " + p.pipeAlive + "<br />\r\n");
361+
builder.append("::: pipe " + p.pipeKey + " size : " + size + " / " + p.pipeAlive + "<br />\r\n");
361362
} else {
362-
buffer.append("Error pipe " + key + " with size : " + size + "<br />\r\n");
363+
builder.append("Error pipe " + key + " with size : " + size + "<br />\r\n");
363364
}
364365
//}
365366
}
366367
}
367368
}
368-
return buffer.toString();
369+
return builder.toString();
369370
}
370371

371372
@J2SIgnore
@@ -404,7 +405,9 @@ private static void monitoringAllPipes() {
404405
if (now - pipe.lastLiveDetected > pipe.pipeWaitClosingInterval()) {
405406
String pipeKey = pipe.pipeKey;
406407
asyncDestroyPipe(pipe);
407-
removePipe(pipeKey);
408+
if (pipeKey != null && pipeKey.length() > 0) {
409+
removePipe(pipeKey);
410+
}
408411
}
409412
} else {
410413
if (pipe instanceof CompoundPipeRunnable) {
@@ -494,16 +497,22 @@ static void monitoringPipe(SimplePipeRunnable pipe) {
494497
return;
495498
}
496499
monitored = true;
497-
ThreadUtils.runTask(new Runnable() {
500+
501+
Thread monitorThread = new Thread(new Runnable() {
498502
public void run() {
499503
monitoringAllPipes();
500504
}
501-
}, "Managed Pipe Session Monitor", true);
502-
ThreadUtils.runTask(new Runnable() {
505+
}, "Simple Pipe Managed Session Monitor");
506+
monitorThread.setDaemon(true);
507+
monitorThread.start();
508+
509+
Thread killThread = new Thread(new Runnable() {
503510
public void run() {
504511
killingPipes();
505512
}
506-
}, "Managed Pipe Session Killer", true);
513+
}, "Simple Pipe Managed Session Killer");
514+
killThread.setDaemon(true);
515+
killThread.start();
507516
}
508517

509518
}

0 commit comments

Comments
 (0)