T***B 发帖数: 137 | 1 在工作中要解决一个scale相关的问题。现有的code简化后大约是这样:
class Predictor {
public Predictor() {
// time consuming stuff.
}
String synchronized predict(String input) {
String result = null;
// step 1
// step 2
// step 3
return result;
}
}
class PredictSvc {
private Predictor predictor = new Predictor();
public List handleRequest() {
List results = new ArrayList();
int count = getCount();
for (int i = 0; i < count; ++i) {
String input = getInput();
String result = predictor.predict(input);
results.add(result);
}
return results;
}
}
现在的问题是这个count有时候很大,导致handleRequest() 执行时间太长。我现在的
想法是做一个thread pool,每一个thread own一个Predictor object. 这样的话在
handleRequest()里就可以同时递交多个predict请求。我学习了一下
ThreadPoolExecutor以及Runnable/Callable, 注意到这些办法好像不能直接take
input parameter.
想问问各位高手这个问题用什么方法并行处理比较好? 谢谢。 |
g*****g 发帖数: 34805 | 2 Nothing stops you from passing the values in the constructor
Predictor implements Runnable
ExcutorService.execute(new Predictor(input)) |
T***B 发帖数: 137 | 3 The problem is the Predictor constructor needs to do some heavy lifting work
thus is slow. I am thinking to pre-create a bunch of Predictor objects and
put them in a BlockingQueue. Once predict() is called, the handler dequeues
a predictor and pass it to ExecutorService. |
f*******t 发帖数: 7549 | 4 constructor为什么slow?不能优化一下吗?
另外这个handleRequest()为什么slow?要找出原因再对症下药。如果它消耗很大CPU资
源,用threadpool执行不一定能提升效率;如果是synchronous地等待什么external
resource,多线程也许有帮助,不过也可能引入race condition和死锁等问题。 |
c*********e 发帖数: 16335 | 5 别在constructor里做费时的事情,最好把new时不必要做的事情,放在一个新的method
里,要用的时候才call那个method.
【在 T***B 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 在工作中要解决一个scale相关的问题。现有的code简化后大约是这样: : class Predictor { : public Predictor() { : // time consuming stuff. : } : String synchronized predict(String input) { : String result = null; : // step 1 : // step 2 : // step 3
|
g*****g 发帖数: 34805 | 6 This is a classic producer/consumer problem then, you should be able to find
many examples online. You could create a fix thread threadpool, and the
same number of Predictor, you then pass predictor and your input to your
jobs before sending them to executor.
work
and
dequeues
【在 T***B 的大作中提到】![](/moin_static193/solenoid/img/up.png) : The problem is the Predictor constructor needs to do some heavy lifting work : thus is slow. I am thinking to pre-create a bunch of Predictor objects and : put them in a BlockingQueue. Once predict() is called, the handler dequeues : a predictor and pass it to ExecutorService.
|
l*******m 发帖数: 1096 | 7 是SVM classifier吧。你这个应该可以。主要缺点是多个model的copies。当然如果不
是太大,这样倒是省心。如果太大,把model本身(一堆矩阵)独立出来,设成global
object就好了
work
and
dequeues
【在 T***B 的大作中提到】![](/moin_static193/solenoid/img/up.png) : The problem is the Predictor constructor needs to do some heavy lifting work : thus is slow. I am thinking to pre-create a bunch of Predictor objects and : put them in a BlockingQueue. Once predict() is called, the handler dequeues : a predictor and pass it to ExecutorService.
|
o**2 发帖数: 168 | 8 你的代码和楼主的代码并不等价。你的是one input per instance,他的是one input
per method invocation。
ExcutorService/Task不容易接收参数的问题我已经在FMP vs ExecutorService/Future
的 4 楼阐述过了。
FMP vs ExecutorService/Future
http://www.mitbbs.com/article_t0/Programming/31258897.html
【在 g*****g 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Nothing stops you from passing the values in the constructor : Predictor implements Runnable : ExcutorService.execute(new Predictor(input))
|
o**2 发帖数: 168 | |
T***B 发帖数: 137 | 10 谢谢各位的回答。
oop2: getInput()不需要等待。对,我是one input (and output) per method. (我现
在不方便,晚上再去拜读你的文章)
lightroom: global object 会有bottleneck在Predictor.predict(), 因为它是
synchronized.
goodbug: 如果采用producer/consumer pattern, 你觉得什么是producer, 什么是
consumer, 什么是work queue 比较好 |
|
|
T***B 发帖数: 137 | 11 fantasist: constructor没法更多优化了。predict calls are CPU intensive. multi
threading should help since our servers have 8/16 cores. |
T***B 发帖数: 137 | 12 I modified the code in the original post a little bit to make it clearer. |
s******e 发帖数: 493 | 13 Executor framework allows you to specify your own thread factory for
creating the threads. If you have to associate one predicator class to each
thread, you can do it there. But since predicator class is expensive to
create, you'd better ask yourself if it is absolutely needed for each thread
having its own predicator instance.
After that, you can simply implement callable interface, pass the input to
the constructor of the implemented class and save the input as a class
variable for use later. Also you can use CompeleteService to retrieve all
the computing results. |
c*********e 发帖数: 16335 | 14 constructor里面到底是什么,怎么这么花时间?
multi
【在 T***B 的大作中提到】![](/moin_static193/solenoid/img/up.png) : fantasist: constructor没法更多优化了。predict calls are CPU intensive. multi : threading should help since our servers have 8/16 cores.
|
o**2 发帖数: 168 | 15 我用FMP把楼主的程序重写了一遍,在这里分多层贴出来,供楼主参考,也欢迎大家评
论。
FMP的binary可以在这里download:http://search.maven.org/#browse|1968728870
Predictor class完全没有变化,我加的都是些print outs。
public class Predictor {
private static int sn = 0;
private synchronized static int incSN () {
return sn++;
}
private String mySN = "Predictor#" + incSN ();
public Predictor () {
System.out.println (mySN + " is starting - " + Thread.currentThread
().getName ());
// time consuming stuff.
System.out.println (mySN + " is ending");
}
public synchronized String predict (String input) {
System.out.println (mySN + " predict(" + input + ") is starting - "
+ Thread.currentThread ().getName ());
// time consuming stuff.
System.out.println (mySN + " predict(" + input + ") is ending");
return input;
}
} |
o**2 发帖数: 168 | 16 PredictSvc class也没有变化,因为在FMP改写后,被一个新的FmpPredictSvc class取
代了。
public class PredictSvc {
private Predictor predictor = new Predictor ();
public List handleRequest (List inputs) {
List results = new ArrayList ();
for (int i = 0; i < inputs.size (); ++i) {
String result = predictor.predict (inputs.get (i));
results.add (result);
}
return results;
}
} |
o**2 发帖数: 168 | 17 新加了PredictorCreator class,因为楼主说Predictor的constructor太CPU
intensive了,我又不确定是否能改写成普通method。由于FMP处理不了constructor,
所以把它移到了一个普通method,这样FMP就可以处理了。
public class PredictorCreator {
public Predictor createPredictor () {
return new Predictor ();
}
} |
T***B 发帖数: 137 | 18 I downloaded FMP library and tried it out. the FMP interface is very
intuitive - I like it. Here is my test code:
Predictor.java
public class Predictor {
private String name;
public Predictor(String name) {
// heavy lifting stuff.
this.name = name;
}
public synchronized String predict(String input) throws
InterruptedException {
System.out.println(name + ": making predict for " + input);
Thread.sleep(100);
System.out.println(name + ": done predicting " + input);
return input + "-blah";
}
TestFmp.java
public class TestFmp {
private static IMessenger messenger;
private static List predictorNames = new ArrayList();
private final static int predictorCount = 10;
private final static int predictionCount = 1000;
private final static List> results = new ArrayList<
IReturn>();
public static void main(String[] args) throws InterruptedException,
ExecutionException {
messenger = new Messenger ();
createPredictorsAndRegister();
long start = System.currentTimeMillis();
makePredictionRequests();
getResults();
long end = System.currentTimeMillis();
System.out.println("Finished all predictions. Time used = "+ ((end-
start)/1000) + " seconds.");
}
private static void createPredictorsAndRegister() {
for (int i = 0; i < predictorCount; ++i) {
String predictorName = "p" + i;
Predictor p = new Predictor(predictorName);
predictorNames.add(predictorName);
messenger.registerReceiver (p, predictorName, "predict");
}
}
private static void makePredictionRequests() {
for (int i = 0; i < predictionCount; ++i) {
String predictorToUse = predictorNames.get(i % predictorCount);
System.out.println("use predictor " + predictorToUse);
IReturn deferred = messenger.callService (predictorToUse
+ ":predict", "i-am-"+i);
results.add(deferred);
}
}
private static void getResults() {
for (IReturn result : results) {
String product = result.get ();
System.out.println("Got " + product);
}
}
} |
T***B 发帖数: 137 | 19 smectite: Yes, I wanted to associate predictor objects to threads in the
pool. Thanks for pointing out Executor framework allows injecting of custom
threads. I will look into it. |
o**2 发帖数: 168 | 20 这个FmpPredictSvc是原先PredictSvc的替换。因为在FMP版中,Predictor变成了
active object,于是使用的方法也必须调整。
我在这里解释一下这个"predictor",因为在第一个for loop中,我们把所有的input
strings都用messenger.callService() method 发给了这个"predictor",那为什么
它能并发呢?
这是因为"predictor"在Main class里被创建成了一个cluster,就是一个active
object名下有多个active implementation objects,impl object的个数就相当于该
cluster的容量。当这样一个active object接收call request的时候,messenger会自
动把request分配给空闲的impl object,直到所有的impl object都变忙了。
于是第一个loop是把requests全发给"predictor",收到相应数量的Future,也就是
IReturn instances。第二个loop则把所有的IReturn的返回值都提取出来,相当于
invoke all。
import java.util.ArrayList;
import java.util.List;
import com.fastmessenger.model.IMessenger;
import com.fastmessenger.model.IReturn;
public class FmpPredictSvc {
private IMessenger messenger;
public FmpPredictSvc (IMessenger messenger) {
this.messenger = messenger;
}
public List handleRequest (List inputs) {
ArrayList> retFutureList = new ArrayList
String>> ();
ArrayList results = new ArrayList ();
for (int i = 0; i < inputs.size (); ++i) {
// async call
IReturn retFuture = messenger.callService ("predictor:
predict", inputs.get (i));
retFutureList.add (retFuture);
}
for (IReturn retFuture : retFutureList) {
String result = retFuture.get (); // blocking call
results.add (result);
}
return results;
}
} |
|
|
o**2 发帖数: 168 | 21 最后这个Main class算是user program里设置active objects的地方。
其中的"builder"是用来执行费时的constructor,也是一个cluster,用法和上面介绍
的"predictor"是一样。
import java.util.ArrayList;
import java.util.List;
import com.fastmessenger.impl.Messenger;
import com.fastmessenger.model.IMessenger;
import com.fastmessenger.model.IReturn;
public class Main {
public static void main (String[] args) {
List inputs = new ArrayList ();
for (int i = 0; i < 10; i++) {
inputs.add ("input" + i);
}
// --- OLD user program ---
PredictSvc predictSvc = new PredictSvc ();
predictSvc.handleRequest (inputs);
System.out.println ("\n\n");
// --- FMP user program ---
IMessenger messenger = new Messenger ();
int cores = Runtime.getRuntime ().availableProcessors ();
// Block A
PredictorCreator[] creatorArray = new PredictorCreator[cores];
for (int i = 0; i < cores; i++) {
creatorArray[i] = new PredictorCreator ();
}
// create active object "builder" which is a cluster
messenger.registerReceiver (creatorArray, "builder", "
createPredictor");
// Block B
ArrayList> retFutureList = new ArrayList
Predictor>> ();
for (int i = 0; i < cores; i++) {
// async call
IReturn retFuture = messenger.callService ("builder:
createPredictor");
retFutureList.add (retFuture);
}
// Block C
Predictor[] predictorArray = new Predictor[cores];
for (int i = 0; i < cores; i++) {
predictorArray[i] = retFutureList.get (i).get (); // blocking
call
}
// create active object "predictor" which is a cluster
messenger.registerReceiver (predictorArray, "predictor", "predict");
// user program invokes handleRequest (inputs) the same as before
FmpPredictSvc fmpPredictSvc = new FmpPredictSvc (messenger);
fmpPredictSvc.handleRequest (inputs);
}
} |
o**2 发帖数: 168 | 22 再贴点运行结果,供没空动手的同学参考。
Predictor#0 is starting - main
Predictor#0 is ending
Predictor#0 predict(input0) is starting - main
Predictor#0 predict(input0) is ending
Predictor#0 predict(input1) is starting - main
Predictor#0 predict(input1) is ending
Predictor#0 predict(input2) is starting - main
Predictor#0 predict(input2) is ending
Predictor#0 predict(input3) is starting - main
Predictor#0 predict(input3) is ending
Predictor#0 predict(input4) is starting - main
Predictor#0 predict(input4) is ending
Predictor#0 predict(input5) is starting - main
Predictor#0 predict(input5) is ending
Predictor#0 predict(input6) is starting - main
Predictor#0 predict(input6) is ending
Predictor#0 predict(input7) is starting - main
Predictor#0 predict(input7) is ending
Predictor#0 predict(input8) is starting - main
Predictor#0 predict(input8) is ending
Predictor#0 predict(input9) is starting - main
Predictor#0 predict(input9) is ending
Predictor#1 is starting - pool-1-thread-2
Predictor#1 is ending
Predictor#2 is starting - pool-1-thread-2
Predictor#3 is starting - pool-1-thread-4
Predictor#3 is ending
Predictor#4 is starting - pool-1-thread-3
Predictor#4 is ending
Predictor#2 is ending
Predictor#1 predict(input0) is starting - pool-1-thread-1
Predictor#1 predict(input0) is ending
Predictor#2 predict(input1) is starting - pool-1-thread-4
Predictor#2 predict(input1) is ending
Predictor#3 predict(input2) is starting - pool-1-thread-3
Predictor#3 predict(input2) is ending
Predictor#4 predict(input3) is starting - pool-1-thread-2
Predictor#4 predict(input3) is ending
Predictor#4 predict(input4) is starting - pool-1-thread-2
Predictor#4 predict(input4) is ending
Predictor#1 predict(input5) is starting - pool-1-thread-1
Predictor#1 predict(input5) is ending
Predictor#2 predict(input6) is starting - pool-1-thread-4
Predictor#2 predict(input6) is ending
Predictor#2 predict(input7) is starting - pool-1-thread-4
Predictor#2 predict(input7) is ending
Predictor#3 predict(input8) is starting - pool-1-thread-2
Predictor#3 predict(input8) is ending
Predictor#4 predict(input9) is starting - pool-1-thread-3
Predictor#4 predict(input9) is ending |
o**2 发帖数: 168 | 23 You got it :)
FMP支持active object cluster,所以程序可以写得稍微更简单一点。
【在 T***B 的大作中提到】![](/moin_static193/solenoid/img/up.png) : I downloaded FMP library and tried it out. the FMP interface is very : intuitive - I like it. Here is my test code: : Predictor.java : public class Predictor { : private String name; : : public Predictor(String name) { : // heavy lifting stuff. : this.name = name; : }
|
g*****g 发帖数: 34805 | 24 你这个也太夸张了吧。一个constructor有多难,对轻量级的task类,用constructor放
一个
参数进去,对性能根本没影响。
input
Future
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 你的代码和楼主的代码并不等价。你的是one input per instance,他的是one input : per method invocation。 : ExcutorService/Task不容易接收参数的问题我已经在FMP vs ExecutorService/Future : 的 4 楼阐述过了。 : FMP vs ExecutorService/Future : http://www.mitbbs.com/article_t0/Programming/31258897.html
|
g*****g 发帖数: 34805 | 25 You init N threads threadpool, each thread is associated with a Predictor,
you simply pass your task to the threadpool.
【在 T***B 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 谢谢各位的回答。 : oop2: getInput()不需要等待。对,我是one input (and output) per method. (我现 : 在不方便,晚上再去拜读你的文章) : lightroom: global object 会有bottleneck在Predictor.predict(), 因为它是 : synchronized. : goodbug: 如果采用producer/consumer pattern, 你觉得什么是producer, 什么是 : consumer, 什么是work queue 比较好
|
o**2 发帖数: 168 | 26 int cores = Runtime.getRuntime ().availableProcessors ();
补充一点,default的new Messenger()使用上面的core数量作为threadpool的容量。
如果不涉及IO,光是计算的话,这些threads足够用了,超过硬件的core数的话,就浪
费了。 |
T***B 发帖数: 137 | 27 照着mectite,goodbug二位的思路写了一下,代码如下. 试着跑了一下,运行结果和预
期吻合。我有一个问题:我在PredictRequest.call()里面把current thread cast成
PredictorThread从而拿到predictor object. 还有更好的办法把predictor (inside
the thread) 和callable联系起来吗?
Predictor.java
public class Predictor {
private String name;
public Predictor(String name) {
// heavy lifting stuff.
this.name = name;
System.out.println("Created predictor " + name);
}
public synchronized String predict(String input) throws
InterruptedException {
System.out.println(name + ": making predict for " + input);
Thread.sleep(1000);
return input + "-blah";
}
}
PredictorThread.java
public class PredictorThread extends Thread {
private static final AtomicInteger created = new AtomicInteger();
private Predictor p;
public PredictorThread(Runnable runnable) {
super(runnable, "p" + created.incrementAndGet());
p = new Predictor("p" + created.get());
System.out.println("creating predictor thread " + this.getName());
}
public Predictor getPredictor() {
return p;
}
}
PredictorThreadFactory.java
public class PredictorThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable runnable) {
return new PredictorThread(runnable);
}
}
PredictRequest.java
public class PredictRequest implements Callable{
private String input;
public PredictRequest(String input) {
this.input = input;
}
@Override
public String call() throws Exception {
PredictorThread thread = (PredictorThread) Thread.currentThread();
// Are there better ways to tie preditor to PredictRequest?
return thread.getPredictor().predict(input);
}
}
PredictService.java
public class PredictService {
private final ExecutorService executor;
public PredictService(int numWorker) {
executor = new ThreadPoolExecutor(
numWorker, numWorker, 1, TimeUnit.MINUTES,
new ArrayBlockingQueue(100, false),
new PredictorThreadFactory());
}
Future predict(String input) throws InterruptedException,
ExecutionException {
return executor.submit(new PredictRequest(input));
}
} |
o**2 发帖数: 168 | 28 ThreadLocal
【在 T***B 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 照着mectite,goodbug二位的思路写了一下,代码如下. 试着跑了一下,运行结果和预 : 期吻合。我有一个问题:我在PredictRequest.call()里面把current thread cast成 : PredictorThread从而拿到predictor object. 还有更好的办法把predictor (inside : the thread) 和callable联系起来吗? : Predictor.java : public class Predictor { : private String name; : : public Predictor(String name) { : // heavy lifting stuff.
|
g*****g 发帖数: 34805 | 29 Put the predictors in a blocking queue. In your Callable do a queue.get and
queue.put before and after, the code is much cleaner. You don't need to
synchronize in the Predictor BTW.
【在 T***B 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 照着mectite,goodbug二位的思路写了一下,代码如下. 试着跑了一下,运行结果和预 : 期吻合。我有一个问题:我在PredictRequest.call()里面把current thread cast成 : PredictorThread从而拿到predictor object. 还有更好的办法把predictor (inside : the thread) 和callable联系起来吗? : Predictor.java : public class Predictor { : private String name; : : public Predictor(String name) { : // heavy lifting stuff.
|
T***B 发帖数: 137 | 30 goodbug, I like your idea of putting predictors in a blocking queue. thanks.
My real implementation of predict method has to be synchronized to
ensure thread safety. Synchronization on this method is the primary
reason that I need a group of preditor objects (as opposed to one)
to avoid the performance bottleneck in this method when multiple threads
are making predict calls. |
|
|
g*****g 发帖数: 34805 | 31 In the proposed change, your predictors are not shared by threads. And you
don't need to sync them.
thanks.
【在 T***B 的大作中提到】![](/moin_static193/solenoid/img/up.png) : goodbug, I like your idea of putting predictors in a blocking queue. thanks. : My real implementation of predict method has to be synchronized to : ensure thread safety. Synchronization on this method is the primary : reason that I need a group of preditor objects (as opposed to one) : to avoid the performance bottleneck in this method when multiple threads : are making predict calls.
|
s******e 发帖数: 493 | 32 Using queue, especially blocking queue, even on the surface looks more
elegant since you can avoid casting. But it actually will cost you more
trouble down the road if you want any nontrivial implementation.
By separating something really closed to each other, you need to handle
their life cycles separately for any elegant implementation. Issues you
might need to consider:
1. The queue should have the exactly same life cycle as the thread if the
predicator instances won't be used anywhere else. if the executor framework
is shutdown, so be the queue.
2. depending on the thread creation policy, the queue might need to shrink
or keep constant with thread pool. This means that when the thread dies or
recreates, the predicator instance needs to follow; also when the predicator
cannot be put back to queue due to the exception, you need to handle it too
; there might be other issues for example that predicator in corrupted
states if you dimply return it to queue in finally block during the
exception...
There might be some other issues which you will only find out down the road.
The above is just trying to help you understand the pros and cons of the
each method. In the end, you are the one who knows the situation and what
you want. just think about it thoroughly... |
o**2 发帖数: 168 | 33 把FMP的版本又优化了一下,很容易就把constructor()和predict()给放到一个active
object里去了,不但constructor()的执行是在worker thread里,而且是on demand的。
在使用原Predictor class的前提下,只增加了PredictorActiveObject和
PredictService这两个classes。
// FMP guarantees every instance a single-threaded env
public class PredictorActiveObject {
private static final AtomicInteger created = new AtomicInteger ();
private Predictor predictor;
// single-threaded
public void init () {
if (predictor == null) {
predictor = new Predictor ("p" + created.incrementAndGet ());
}
}
// single-threaded
public String predict (String input) throws Exception {
init ();
return predictor.predict (input);
}
}
public class PredictService {
private IMessenger messenger;
public PredictService () {
int cores = Runtime.getRuntime ().availableProcessors ();
PredictorActiveObject[] pArray = new PredictorActiveObject[cores];
for (int i = 0; i < cores; i++) {
pArray[i] = new PredictorActiveObject ();
}
messenger = new Messenger ();
messenger.registerReceiver (pArray, "predictor", "init", "predict");
}
public List handleRequest (List inputs) {
ArrayList> retFutureList = new ArrayList
String>> ();
ArrayList results = new ArrayList ();
for (int i = 0; i < inputs.size (); ++i) {
// async call
IReturn retFuture = messenger.callService ("predictor:
predict", inputs.get (i));
retFutureList.add (retFuture);
}
for (IReturn retFuture : retFutureList) {
String result = retFuture.get (); // blocking call
results.add (result);
}
return results;
}
} |
o**2 发帖数: 168 | 34 如果楼主可以把contructor()里的logic搬到一个init() method里的话,那就没有必要
加新class了,改造原先的Predictor和PredictService就够用的了。
从下面列出原问题的FMP终结版可以看出,FMP和thread,thread pool,
ExecutorService等并发编程技术相比,就象C语言和汇编语言相比,那是全方面的胜出。
public class Predictor {
private boolean inited = false;
// instance-wide single-threaded
public void init () {
if (inited) {
return;
} else {
inited = true;
}
// heavy lifting stuff from original constructor
}
// instance-wide single-threaded
public String predict (String input) {
init ();
// CPU intensive work
return input + "-blah";
}
}
public class PredictService {
private IMessenger messenger;
public PredictService () {
int cores = Runtime.getRuntime ().availableProcessors ();
Predictor[] pArray = new Predictor[cores];
for (int i = 0; i < cores; i++) {
pArray[i] = new Predictor ();
}
messenger = new Messenger ();
messenger.registerReceiver (pArray, "predictor", "init", "predict");
// optional - forced initialization
for (int i = 0; i < cores; i++) {
messenger.sendMessage ("predictor:init");
}
}
public List handleRequest (List inputs) {
ArrayList> retFutureList = new ArrayList
String>> ();
ArrayList results = new ArrayList ();
for (int i = 0; i < inputs.size (); ++i) {
IReturn retFuture = messenger.callService ("predictor:
predict", inputs.get (i));
retFutureList.add (retFuture);
}
for (IReturn retFuture : retFutureList) {
String result = retFuture.get ();
results.add (result);
}
return results;
}
} |
c*********e 发帖数: 16335 | 35 好奇地问一下,这些class是用在web application里,还是application里?
如果是web application里,每一個用戶登录进去后,private boolean inited的值,
每个用戶都能更改,因为它不是session variable.这个大家怎么解决的?
public class Predictor {
private boolean inited = false;
出。
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 如果楼主可以把contructor()里的logic搬到一个init() method里的话,那就没有必要 : 加新class了,改造原先的Predictor和PredictService就够用的了。 : 从下面列出原问题的FMP终结版可以看出,FMP和thread,thread pool, : ExecutorService等并发编程技术相比,就象C语言和汇编语言相比,那是全方面的胜出。 : public class Predictor { : private boolean inited = false; : // instance-wide single-threaded : public void init () { : if (inited) { : return;
|
o**2 发帖数: 168 | 36 我不是很理解你的问题,这些是POJO,用在哪里它都遵循Java language的定义啊。
根据楼主的介绍,我估计他的程序要么是一个batch job,要么是一个back office的
engine。这些class的instance肯定不是直接为每一个http connection创建和服务的。
【在 c*********e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 好奇地问一下,这些class是用在web application里,还是application里? : 如果是web application里,每一個用戶登录进去后,private boolean inited的值, : 每个用戶都能更改,因为它不是session variable.这个大家怎么解决的? : public class Predictor { : private boolean inited = false; : : 出。
|
c*********e 发帖数: 16335 | 37 抱歉。因为我web application做得很多,所以对session variable很敏感。
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 我不是很理解你的问题,这些是POJO,用在哪里它都遵循Java language的定义啊。 : 根据楼主的介绍,我估计他的程序要么是一个batch job,要么是一个back office的 : engine。这些class的instance肯定不是直接为每一个http connection创建和服务的。
|
T***B 发帖数: 137 | 38 smectite, you raised an very important point.
If we start with the requirements, what I need is a group of predictors that
can independently make predictions within a JVM. Some characteristics of
the system:
- Initializing a predictor is time consuming.
- A predictor, once initialized, holds non-trivial amount of memory.
- Predict call is CPU intensive. predict() method is not thread safe.
- A client request triggers a batch of predict calls. Batch size can vary.
From design perspective, what I'd like to have:
- We need to maintain a fix sized predictor pool. The predictors will be
initialized as soon as the service starts. We need a mechanism to clean up
bad/corrupted predictors and add new one to the pool to keep its size in
balance.
- If the number of concurrent predict requests exceeds the predictor
capacity, we need to put the requests in a pending queue and serve them in a
FIFO fashion.
Now down to implementation. Looks to me Java's ThreadPoolExecutor framework
can do majority of the work for me. What I need to address include:
- hook up the predictors with the threads in the pool. I am kind of
convinced that it is better to implement the predictor as a thread as
opposed to a separate queue due to the reasons you raised.
- deal with input/output parameters' passing (already solved).
oop2's FMP solution is very elegant too - the interface is even simpler than
ThreadPoolExecutor. What I am curious is FMP framework's overhead in terms
of performance. I will probably run some performance benchmarks with both
solutions.
Thanks everybody for your help. I learned a lot from you. |
g*****g 发帖数: 34805 | 39 I think the problem is overstated. When the predictors are kept in a
separate blocking queue, they don't have to have the same life cycle as
threadpool, which gives you more flexiblity. And if you want to tie them,
you can always override shutdown method of the threadpool. Also Predictor is
not affected by predict calls, I don't see how they can be corrupted.
In fact, in a complicated server app, this separation makes it possible to
send these tasks to a generic threadpool.
framework
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Using queue, especially blocking queue, even on the surface looks more : elegant since you can avoid casting. But it actually will cost you more : trouble down the road if you want any nontrivial implementation. : By separating something really closed to each other, you need to handle : their life cycles separately for any elegant implementation. Issues you : might need to consider: : 1. The queue should have the exactly same life cycle as the thread if the : predicator instances won't be used anywhere else. if the executor framework : is shutdown, so be the queue. : 2. depending on the thread creation policy, the queue might need to shrink
|
s******e 发帖数: 493 | 40 well I believe it was understated in this use case. What concern the author
most were performance and memory footprint. By take advantage of the built-
in life cycle mechanism of the executor framework, coders can very much
delegate the predicator instance management to the executor framework. This
will guarantee both the performance (no thread needs to wait for next
available predicator instance) and memory footprint concerns (shrink and
recreates if needed. or fixed...) this provides the exact flexibilities a
good api needs to provide for any "complicated" system. On the other side, I
really do not see any flexibility with a separate resource queue for
predicators. Since in this case the thread pool pretty much the only
consumer of the the resource pool, by nature, they are tightly coupled, in
order to achieve the functionalities above, It will burden the coders to
build the communication mechanism between two pools (Actually the queue can
be viewd as a very naive pool). Also mixing the thread pool with some
computing intense jobs and less expensive tasks is never a good idea and
practice.
Depending on the requirements, your design might fly in other use cases,
but based on what the author said, I do not think it fits in this situation.
In the end, use cases and biz requirements should always drive your design,
rather than design by good practice you think and try to cover your
requirements later.
Any mutable and stateful class can be corrupted during the method execution
due to the exception. Considering the excess initial loading time and big
memory footprint as the author specified, it is hard to image that the
predicator class is stateless and immutable. If you have ever play with
apache common pools, you will notice that pool resource are usually
validated and reset to avoid state corruption before being returned to the
pool. But i am not sure in this case if predicator can be easily reset to
the initial states when that happens, but I am pretty sure you have to code
validation and reset mechanisms for a robust implementation or use common
pool rather than raw blocking queue.
is
【在 g*****g 的大作中提到】![](/moin_static193/solenoid/img/up.png) : I think the problem is overstated. When the predictors are kept in a : separate blocking queue, they don't have to have the same life cycle as : threadpool, which gives you more flexiblity. And if you want to tie them, : you can always override shutdown method of the threadpool. Also Predictor is : not affected by predict calls, I don't see how they can be corrupted. : In fact, in a complicated server app, this separation makes it possible to : send these tasks to a generic threadpool. : : framework
|
|
|
o**2 发帖数: 168 | 41 Give each Predictor object its own thread, and apply producer/consumer
pattern twice: one is from user thread to predictor thread for dropping off
prediction input, and the other one is form predictor thread to user thread
for picking up computed prediction.
public class Predictor implements Runnable {
private String input, prediction;
private boolean stop;
public Predictor () {
new Thread (this).start ();
}
public synchronized boolean isIdle () {
return input == null;
}
public synchronized boolean isComputing () {
return input != null && prediction == null;
}
public synchronized boolean isReady () {
return input != null && prediction != null;
}
public synchronized void predict (String userInput) {
if (!isIdle ()) {
throw new IllegalStateException ("Must invoke predict()/
prediction () in pair.");
}
input = userInput;
this.notify ();
}
public synchronized String prediction () {
if (isIdle ()) {
throw new IllegalStateException ("Must invoke predict()/
prediction () in pair.");
}
if (isComputing ()) {
try {
this.wait ();
} catch (InterruptedException e) {
// not likely to happen
e.printStackTrace ();
return null;
}
}
String result = prediction;
input = prediction = null;
return result;
}
public synchronized void stop () {
stop = true;
this.notify ();
}
public void run () {
myInit ();
while (true) {
String threadInput = null;
synchronized (this) {
if (stop) {
input = prediction = null;
this.notify ();
return;
} else if (isComputing ()) {
threadInput = input;
} else {
try {
this.wait ();
} catch (InterruptedException e) {
// not likely to happen
e.printStackTrace ();
return;
}
}
}
if (threadInput != null) {
String threadResult = myPredict (threadInput);
synchronized (this) {
prediction = threadResult;
this.notify ();
}
}
}
}
private void myInit () {
// heavy lifting stuff in the original constructor
}
private String myPredict (String input) {
// CPU intensive work in the origianl predict()
return input + "-blah";
}
}
public class PredictorService {
ArrayList predictorList;
public synchronized void start () {
int cores = Runtime.getRuntime ().availableProcessors ();
predictorList = new ArrayList (cores);
for (int i = 0; i < cores; i++) {
predictorList.add (new Predictor ());
}
}
public synchronized void stop () {
for (Predictor predictor : predictorList) {
predictor.stop ();
}
}
public synchronized List predict (List inputList) {
String[] inputArray = inputList.toArray (new String[inputList.size (
)]);
ArrayList resultList = new ArrayList (inputList.size
());
int inputPos = 0;
int inputRemainingSize = inputList.size ();
while (inputRemainingSize > 0) {
int batchSize = Math.min (inputRemainingSize, predictorList.size
());
predict (inputArray, inputPos, predictorList, batchSize,
resultList);
inputPos += batchSize;
inputRemainingSize -= batchSize;
}
return resultList;
}
private void predict (String[] inputArray, int inputPos, ArrayList<
Predictor> predictorList,
int batchSize, ArrayList resultList) {
for (int i = 0; i < batchSize; i++) {
predictorList.get (i).predict (inputArray[inputPos + i]);
}
for (int i = 0; i < batchSize; i++) {
resultList.add (predictorList.get (i).prediction ());
}
}
} |
c*********e 发帖数: 16335 | 42 高手,这code你写的吗?
off
thread
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Give each Predictor object its own thread, and apply producer/consumer : pattern twice: one is from user thread to predictor thread for dropping off : prediction input, and the other one is form predictor thread to user thread : for picking up computed prediction. : public class Predictor implements Runnable { : private String input, prediction; : private boolean stop; : public Predictor () { : new Thread (this).start (); : }
|
o**2 发帖数: 168 | 43 我在mitbbs上混了几个月了,一直是码工本色,用代码说话,你没有注意到吗?那我还
要再多写代码才行。
这是很简单的应用producer/consumer的例子,虽然很多行,但概念很简单,十分钟就
可以写一个这样的程序。由于主要是给楼主参考借鉴用的,所以也没有检查所有的
thread interleaving的地方,也许会有错。
这个例子也展示了直接用thread写并发程序的困难性:新手入手难,熟手也不能完全保
证正确性。我个人认为楼主的上策应该是选用FMP,中策是选用直接的thread,下策是
thread pool。
【在 c*********e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 高手,这code你写的吗? : : off : thread
|
g*****g 发帖数: 34805 | 44 这年头还有自己从头写的?producer/consumer的例子现成的一大把。
会google会改就够了。
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 我在mitbbs上混了几个月了,一直是码工本色,用代码说话,你没有注意到吗?那我还 : 要再多写代码才行。 : 这是很简单的应用producer/consumer的例子,虽然很多行,但概念很简单,十分钟就 : 可以写一个这样的程序。由于主要是给楼主参考借鉴用的,所以也没有检查所有的 : thread interleaving的地方,也许会有错。 : 这个例子也展示了直接用thread写并发程序的困难性:新手入手难,熟手也不能完全保 : 证正确性。我个人认为楼主的上策应该是选用FMP,中策是选用直接的thread,下策是 : thread pool。
|
o**2 发帖数: 168 | 45 太夸张了吧,这么简单的东西还要google?
【在 g*****g 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 这年头还有自己从头写的?producer/consumer的例子现成的一大把。 : 会google会改就够了。
|
t***a 发帖数: 416 | 46 我只是好奇,为什么你这么喜欢FMP?
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 太夸张了吧,这么简单的东西还要google?
|
r*****s 发帖数: 985 | 47 安啦,
不同牛人的不同表现方式而已。
我也是google的多,
java的好处就是lib一堆,
比如前面那个compare string的,
那管什么"".equals(str)的优化?
直接if(StringUtils.isEmpty(str))就好了。
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 太夸张了吧,这么简单的东西还要google?
|
o**2 发帖数: 168 | 48 FMP is my project.
【在 t***a 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 我只是好奇,为什么你这么喜欢FMP?
|
t***a 发帖数: 416 | 49 大赞阿,看着挺有意思的,支持!
你一个人维护?放哪了?
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : FMP is my project.
|
o**2 发帖数: 168 | 50 Thank you...here are links. You could help if you like the project. Let me
know.
Project
======
http://fastmessenger.com
Blogs
=====
English: http://www.java.net/blogs/rexyoung/
Chinese: http://www.cnblogs.com/rexyoung
Java Reference Implementation
==========================
Source: https://github.com/fastmessenger/RI-in-Java
Binary: http://search.maven.org/#browse|1968728870
Online Javadoc: http://fastmessenger.com/files/java-ref-impl/2.1.0/api/index.html
C# Reference Implementation
========================
Source: https://github.com/fastmessenger/RI-in-Csharp
JavaScript Reference Implementation
==============================
Source: https://github.com/fastmessenger/RI-in-JavaScript
Online demos: http://fastmessenger.com/files/javascript-ref-impl/1.5.0/demo/index.html
【在 t***a 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 大赞阿,看着挺有意思的,支持! : 你一个人维护?放哪了?
|
|
|
r*****s 发帖数: 985 | 51 您老早说啊,
我们都捧捧场,
就是杀鸡也用您牛人的刀!
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : FMP is my project.
|
t***a 发帖数: 416 | 52 不错不错,还有maven, 现在我感觉我都不太会部署local jar了
你那个javascript的fms是啥思路啊?怎么用的?
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Thank you...here are links. You could help if you like the project. Let me : know. : Project : ====== : http://fastmessenger.com : Blogs : ===== : English: http://www.java.net/blogs/rexyoung/ : Chinese: http://www.cnblogs.com/rexyoung : Java Reference Implementation
|
s******e 发帖数: 493 | 53 public Predictor () {
new Thread (this).start ();
}
Interesting... I believe this is against java publication safety rule.
Did you try to run pmd and firebug on it? |
o**2 发帖数: 168 | 54 那太太太感谢了,有github帐号的话就捧捧场吧。
FMP的确可以杀鸡(level of object),也可以屠龙(level of cloud apps)。现在
的切入点是杀鸡工具。
【在 r*****s 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 您老早说啊, : 我们都捧捧场, : 就是杀鸡也用您牛人的刀!
|
o**2 发帖数: 168 | 55 你说的完全有可能,我自己都不熟悉你提到的“java publication safety rule”。
你的第二句是啥意思啊?
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : public Predictor () { : new Thread (this).start (); : } : Interesting... I believe this is against java publication safety rule. : Did you try to run pmd and firebug on it?
|
o**2 发帖数: 168 | 56 FMP在JavaScript里有两个主要用途。一是作为一个组织代码的手段,鼓励function作
为object的method,然后用FMP来access。这样的话,写JS的大程序就容易了。
二是并发编程。JavaScript在browser和Node.js都是同一种thread model,就是每一个
thread(e.g. web worker or sub-process)都有它独享的内存,然后thread之间用
channel来通讯。
Online demo的link在前面已经列出来了。这里有我以前写的两篇blog,是关于FMP和
JavaScript的。
https://weblogs.java.net/blog/rexyoung/archive/2012/05/04/little-details-
about-implementation-fast-messenger-javascript
https://weblogs.java.net/blog/rexyoung/archive/2012/06/25/obsolete-need-help
-confirming-two-firefox-web-worker-bugs
【在 t***a 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 不错不错,还有maven, 现在我感觉我都不太会部署local jar了 : 你那个javascript的fms是啥思路啊?怎么用的?
|
t***a 发帖数: 416 | 57 很有意思,js项目里组织代码一直很困扰我,试了好多方式,到现在也还是摇摆不定,
很纠结
help
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : FMP在JavaScript里有两个主要用途。一是作为一个组织代码的手段,鼓励function作 : 为object的method,然后用FMP来access。这样的话,写JS的大程序就容易了。 : 二是并发编程。JavaScript在browser和Node.js都是同一种thread model,就是每一个 : thread(e.g. web worker or sub-process)都有它独享的内存,然后thread之间用 : channel来通讯。 : Online demo的link在前面已经列出来了。这里有我以前写的两篇blog,是关于FMP和 : JavaScript的。 : https://weblogs.java.net/blog/rexyoung/archive/2012/05/04/little-details- : about-implementation-fast-messenger-javascript : https://weblogs.java.net/blog/rexyoung/archive/2012/06/25/obsolete-need-help
|
r*****s 发帖数: 985 | 58 akka那个是不是跟您这个类似啊,
比较一下?
help
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : FMP在JavaScript里有两个主要用途。一是作为一个组织代码的手段,鼓励function作 : 为object的method,然后用FMP来access。这样的话,写JS的大程序就容易了。 : 二是并发编程。JavaScript在browser和Node.js都是同一种thread model,就是每一个 : thread(e.g. web worker or sub-process)都有它独享的内存,然后thread之间用 : channel来通讯。 : Online demo的link在前面已经列出来了。这里有我以前写的两篇blog,是关于FMP和 : JavaScript的。 : https://weblogs.java.net/blog/rexyoung/archive/2012/05/04/little-details- : about-implementation-fast-messenger-javascript : https://weblogs.java.net/blog/rexyoung/archive/2012/06/25/obsolete-need-help
|
t***a 发帖数: 416 | 59 scala下akka接口还可以,java下,真心不如楼主这一套简单实用
不过akka线程池可以分布式的,不知道楼主这个能部署成分布式的吗
【在 r*****s 的大作中提到】![](/moin_static193/solenoid/img/up.png) : akka那个是不是跟您这个类似啊, : 比较一下? : : help
|
s******e 发帖数: 493 | 60 PMD and findbugs are code style checking tools.
just quickly take a look at your code this page. I believe what you try to
do is exactly what executor framework tries to resolve. Since they do that
in a more elegant way. I do not see why we should reinvent wheels in a much
harder way. |
|
|
t***a 发帖数: 416 | 61 谁能来科普一下 ,什么是java publication safety rule啊,我等下文等了一下午了
。。。。
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 你说的完全有可能,我自己都不熟悉你提到的“java publication safety rule”。 : 你的第二句是啥意思啊?
|
o**2 发帖数: 168 | 62 可以说核心都是actor的思想,akka用户是使用裸体的actor,FMP的用户是通过
messenger使用active object。这个archtecture上的不同导致了vision的完全不同,
FMP完全是跨语言跨平台。不同语言不同平台上的不同active object可以用自始至终不
变的API互相调用/通讯,比如一个C#写的active object在messenger1里在Windows上可
以这样调用另外一个Java写的active object "calculator"which运行在messenger2在
Linux上:
messenger1.callService("messenger2::calculator:multiply", n1, n2);
(当然前提是messenger1和messenger2已经直接或间接地connected,FMP叫它们
networked messengers。模型和设计都完成了,就等有空的时候,我写一个reference
implementation。)
(n1和n2要是合适的数据,比如可以写成JSON的。FMP不管数据转换的。)
简单地说akka是汇编语言级的actor model,FMP是Java语言级(甚至cloud级)的actor
model。
【在 r*****s 的大作中提到】![](/moin_static193/solenoid/img/up.png) : akka那个是不是跟您这个类似啊, : 比较一下? : : help
|
s******e 发帖数: 493 | 63 go read java concurrency in practice. It has the detailed explanation. In
short, for this case, you can not publish a reference of an object to
another thread from its own constructor since the object might not be
appropriately constructed yet. |
o**2 发帖数: 168 | 64 可以,不但是分布的,还可以是跨语言跨平台的。(pls refer to my other replies
,and 现在没有implementation,will be available in near future。)
【在 t***a 的大作中提到】![](/moin_static193/solenoid/img/up.png) : scala下akka接口还可以,java下,真心不如楼主这一套简单实用 : 不过akka线程池可以分布式的,不知道楼主这个能部署成分布式的吗
|
o**2 发帖数: 168 | 65 没有用过code style checking tools。
我把一个thread完全隐含到一个Predictor的instance里面,对这个问题来说,是最符
合OOP设计原则的,同时也符合原要求。虽然内部有很多代码做interleaving的
checking,看起来很繁琐,但原则很简单。会producer/consumer pattern的程序员都
能写和接手这个程序。
Executor framework是基于task的,在这个问题上,只会把class弄的一团糟,后续的
维护和调整将会相当困难,比如一个Predictor的instance有问题了(要检测方便)要
换一个新的instance等。
建议你也动手写一个Executor版本的代码,贴出来我们分析讨论一下。
much
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : PMD and findbugs are code style checking tools. : just quickly take a look at your code this page. I believe what you try to : do is exactly what executor framework tries to resolve. Since they do that : in a more elegant way. I do not see why we should reinvent wheels in a much : harder way.
|
o**2 发帖数: 168 | 66 你说的这个并不是thread特定的问题,当程序进入constructor时,JVM就已经把这个
instance建立起来了,然后的问题就是这个instance的internal state,也就是它的
instance变量,有可能在一个或多个constructor中有变化,而这些变化是不应该暴露
给外面的世界,相当于transaction的内部阶段。
我的代码没有这个问题,Predictor的constructor不改变instance的internal state。
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : go read java concurrency in practice. It has the detailed explanation. In : short, for this case, you can not publish a reference of an object to : another thread from its own constructor since the object might not be : appropriately constructed yet.
|
o**2 发帖数: 168 | 67 顺便提一下,这个问题在Observer pattern多的地方(比如GUI)有可能变得很严重。
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 你说的这个并不是thread特定的问题,当程序进入constructor时,JVM就已经把这个 : instance建立起来了,然后的问题就是这个instance的internal state,也就是它的 : instance变量,有可能在一个或多个constructor中有变化,而这些变化是不应该暴露 : 给外面的世界,相当于transaction的内部阶段。 : 我的代码没有这个问题,Predictor的constructor不改变instance的internal state。
|
s******e 发帖数: 493 | 68 Haha if you can wait... I might write my own executor framework if I really
wanna kill my spare time.
Just do me a favor, go read the book. your code is almost the exact example
they use to show what a bad code will be.
No offense, I know you put tons of efforts in your project and I admire it.
Since I did not really spend any time on looking at your project, I cannot
comment on it. But I have written several wrappers on top of executor
framework for some specific tasks. I really feel that executor framework is
already generic and powerful enough for almost all java based multi-threaded
tasks. Especially if my memory is correct, I believe, under the hood, they
use some hardware synchronization technologies (such as cas) and other
tricks to boost the performance. It would be hard to image any home grown
thread management framework not based on executor framework to beat them
performance wisely.
By the way, since you are doing open source, many a time people will judge
your project by checking your code style instead of spending a good amount
of time to read the glory details. You'd better to learn those coding style
check tools. |
r*****y 发帖数: 264 | 69 Predictor.predict()方法Thread Safe吗?
调用Predictor.predict()处理inputs的每一个item,先后次序有关系吗?
不同时间生成的Predictor对处理结果有影响吗? |
t***a 发帖数: 416 | 70 你说的这个问题很常见,你是对的,在对象创建的过程中,publish它的引用会有产生
问题
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : go read java concurrency in practice. It has the detailed explanation. In : short, for this case, you can not publish a reference of an object to : another thread from its own constructor since the object might not be : appropriately constructed yet.
|
|
|
o**2 发帖数: 168 | 71 你这个太长了,我分楼答复你。
really
example
.
is
threaded
they
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Haha if you can wait... I might write my own executor framework if I really : wanna kill my spare time. : Just do me a favor, go read the book. your code is almost the exact example : they use to show what a bad code will be. : No offense, I know you put tons of efforts in your project and I admire it. : Since I did not really spend any time on looking at your project, I cannot : comment on it. But I have written several wrappers on top of executor : framework for some specific tasks. I really feel that executor framework is : already generic and powerful enough for almost all java based multi-threaded : tasks. Especially if my memory is correct, I believe, under the hood, they
|
o**2 发帖数: 168 | 72 我没有提过让你写“my own executor framework”啊,我是说请你用你认为最好用的
JDK现有的executor framework帮楼主写他的Predictor和PredictorService classes。
我在这个帖子里每次写的code大约都是用十几二十分钟,所以应该不会占用你太多时间。
really wanna kill my spare time.
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Haha if you can wait... I might write my own executor framework if I really : wanna kill my spare time. : Just do me a favor, go read the book. your code is almost the exact example : they use to show what a bad code will be. : No offense, I know you put tons of efforts in your project and I admire it. : Since I did not really spend any time on looking at your project, I cannot : comment on it. But I have written several wrappers on top of executor : framework for some specific tasks. I really feel that executor framework is : already generic and powerful enough for almost all java based multi-threaded : tasks. Especially if my memory is correct, I believe, under the hood, they
|
o**2 发帖数: 168 | 73 我听你的,把第三章的Sharing Objects从第33到54页又读了一遍。发现就是按这本书
里说的标准,你对我的程序的判定也是错的,没有根据的。因为它说的是“Mutable
objects must be safely published, and mush be either thread safe or guarded
by a lock.”。我写的程序(在41楼)完全符合它对安全的定义,就是instance变量都
guarded by a lock。
我在66和67楼的回复中说这是OOP encapsulation的要求,不但对constructor,对任何
一个能change internal state的method,都有这个要求。就是你要等change made,才
能去publish/notify外部的其他objects。
而且我说的OOP encapsulation这个知识,是Brian在第三章说的知识的来源。
example they use to show what a bad code will be.
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Haha if you can wait... I might write my own executor framework if I really : wanna kill my spare time. : Just do me a favor, go read the book. your code is almost the exact example : they use to show what a bad code will be. : No offense, I know you put tons of efforts in your project and I admire it. : Since I did not really spend any time on looking at your project, I cannot : comment on it. But I have written several wrappers on top of executor : framework for some specific tasks. I really feel that executor framework is : already generic and powerful enough for almost all java based multi-threaded : tasks. Especially if my memory is correct, I believe, under the hood, they
|
t***a 发帖数: 416 | 74 我的理解是这样的,两位大侠帮忙看看对不对啊
关于对于object, 如果它的constructor还没有完全运行完,就publish它的reference,
是不安全的,比如说他有成员变量或者inner class没有初始化完之类的问题, 这可
能会让其他thread拿到一个incomplete的对象,我觉得这和oop2大侠说的“instance变
量都guarded by a lock"不是一个事儿.
就算在constructor的最后一行去publish这个object的引用,也是不safe的,因为这里
可能还有子类继承的情况,可能有子类构造函数里初始化未完全
类似的情况还有constructor里面起新的thread...
但如果,这个class的所有成员都是final的呢,即便它的value是在constructor里初始
化的,我的理解是,应该也不会存在incomplete object的问题了,这就是scala cass
class的好处啊!!太爱scala了。。。。
guarded
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 我听你的,把第三章的Sharing Objects从第33到54页又读了一遍。发现就是按这本书 : 里说的标准,你对我的程序的判定也是错的,没有根据的。因为它说的是“Mutable : objects must be safely published, and mush be either thread safe or guarded : by a lock.”。我写的程序(在41楼)完全符合它对安全的定义,就是instance变量都 : guarded by a lock。 : 我在66和67楼的回复中说这是OOP encapsulation的要求,不但对constructor,对任何 : 一个能change internal state的method,都有这个要求。就是你要等change made,才 : 能去publish/notify外部的其他objects。 : 而且我说的OOP encapsulation这个知识,是Brian在第三章说的知识的来源。 :
|
o**2 发帖数: 168 | 75 我完全没有被offensed,你讨论的态度非常positive and professional。
关于我对executor framework的看法,我已经在和goodbug的讨论中(link below)陈述
过了。(goodbug silently退出了讨论。)
FMP vs ExecutorService/Future
http://www.mitbbs.com/article_t0/Programming/31258897.html
简单地说,我的意见和你的相左。Java executor framework比不上C#的async keyword
,就按你说的限制在Java之内的话,也比不过Spring Framework的@Async。
至于你提到的硬件加速等performance boost,那是FMP不care的东西。因为FMP卖的是
spec是标准,你没有注意到我的project是自称为reference implementation吗?
就象C不会去和汇编比速度、也不会自称是汇编代码的management一样,FMP也是自成体
系的。FMP追求的重点是降低程序员写并发程序的门坎,提高程序员的生产率(包括降
低thread相关的错误)。而且速度也不比thread pool低,内部的implementation用的
就是thread pool/executor framework。
. Since I did not really spend any time on looking at your project, I cannot
comment on it. But I have written several wrappers on top of executor
framework for some specific tasks. I really feel that executor framework is
already generic and powerful enough for almost all java based multi-threaded
tasks. Especially if my memory is correct, I believe, under the hood, they
use some hardware synchronization technologies (such as cas) and other
tricks to boost the performance. It would be hard to image any home grown
thread management framework not based on executor framework to beat them
performance wisely.
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Haha if you can wait... I might write my own executor framework if I really : wanna kill my spare time. : Just do me a favor, go read the book. your code is almost the exact example : they use to show what a bad code will be. : No offense, I know you put tons of efforts in your project and I admire it. : Since I did not really spend any time on looking at your project, I cannot : comment on it. But I have written several wrappers on top of executor : framework for some specific tasks. I really feel that executor framework is : already generic and powerful enough for almost all java based multi-threaded : tasks. Especially if my memory is correct, I believe, under the hood, they
|
o**2 发帖数: 168 | 76 这个非常感谢你的忠告,真心的。多数时候光技术是不行的,重要的是不能逆大众的潮
流。
your project by checking your code style instead of spending a good amount
of time to read the glory details. You'd better to learn those coding style
check tools.
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Haha if you can wait... I might write my own executor framework if I really : wanna kill my spare time. : Just do me a favor, go read the book. your code is almost the exact example : they use to show what a bad code will be. : No offense, I know you put tons of efforts in your project and I admire it. : Since I did not really spend any time on looking at your project, I cannot : comment on it. But I have written several wrappers on top of executor : framework for some specific tasks. I really feel that executor framework is : already generic and powerful enough for almost all java based multi-threaded : tasks. Especially if my memory is correct, I believe, under the hood, they
|
o**2 发帖数: 168 | 77 即使同一个thread,如果你在constructor里call其他object,然后那个object又
access回来,还是有拿到一个incomplete的对象的机会的。在并发下,可能性就更大了
一点。
我说的“instance变量都guarded by a lock"是引用原书,是有context的,就是以第
三章的标准去衡量我写的Predictor。如果变量都guarded by a lock,那意味着别的
thread不可能拿到一个incomplete的对象(即变量)。
我的确没有考虑到子类继承,一是我写的Predictor没有子类,二是考虑子类的话,那
复杂度就大了,我估计基本没有什么原则上安全的东西了。我就撤退了,留给你和发考
题了 :)
reference,
cass
【在 t***a 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 我的理解是这样的,两位大侠帮忙看看对不对啊 : 关于对于object, 如果它的constructor还没有完全运行完,就publish它的reference, : 是不安全的,比如说他有成员变量或者inner class没有初始化完之类的问题, 这可 : 能会让其他thread拿到一个incomplete的对象,我觉得这和oop2大侠说的“instance变 : 量都guarded by a lock"不是一个事儿. : 就算在constructor的最后一行去publish这个object的引用,也是不safe的,因为这里 : 可能还有子类继承的情况,可能有子类构造函数里初始化未完全 : 类似的情况还有constructor里面起新的thread... : 但如果,这个class的所有成员都是final的呢,即便它的value是在constructor里初始 : 化的,我的理解是,应该也不会存在incomplete object的问题了,这就是scala cass
|
o**2 发帖数: 168 | 78 抱歉,我几乎霸占了帖子,这个应该是问楼主的,帮你顶一下!
楼主出来之前,我就帮着回答一下:1,不是,一次一个请求;2,没有;3,没有。
【在 r*****y 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Predictor.predict()方法Thread Safe吗? : 调用Predictor.predict()处理inputs的每一个item,先后次序有关系吗? : 不同时间生成的Predictor对处理结果有影响吗?
|
t***a 发帖数: 416 | 79 这个就不想了。。。。anyway,很赞你先前帖子里的那句,可以降级程序写并发程序的
门槛
加油啊
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 即使同一个thread,如果你在constructor里call其他object,然后那个object又 : access回来,还是有拿到一个incomplete的对象的机会的。在并发下,可能性就更大了 : 一点。 : 我说的“instance变量都guarded by a lock"是引用原书,是有context的,就是以第 : 三章的标准去衡量我写的Predictor。如果变量都guarded by a lock,那意味着别的 : thread不可能拿到一个incomplete的对象(即变量)。 : 我的确没有考虑到子类继承,一是我写的Predictor没有子类,二是考虑子类的话,那 : 复杂度就大了,我估计基本没有什么原则上安全的东西了。我就撤退了,留给你和发考 : 题了 :) :
|
s******e 发帖数: 493 | 80 Haha... that makes my day... As you wish, I will quit. but unfortunately,
not that "silently".
【在 o**2 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 抱歉,我几乎霸占了帖子,这个应该是问楼主的,帮你顶一下! : 楼主出来之前,我就帮着回答一下:1,不是,一次一个请求;2,没有;3,没有。
|
|
|
l*******m 发帖数: 1096 | 81 good question. it should be a machine learning service.
predict function should be thread safe. the constructor would be the model
training part. in addition, predict function has nothing to do time and
order. therefore, i think the design could be lighter
【在 r*****y 的大作中提到】![](/moin_static193/solenoid/img/up.png) : Predictor.predict()方法Thread Safe吗? : 调用Predictor.predict()处理inputs的每一个item,先后次序有关系吗? : 不同时间生成的Predictor对处理结果有影响吗?
|