[讨论] 请教一下如何控制JVM中的线程

nkhanxh 2012-02-03
感觉想做os中的抢占式调度。

这个需求怎么这么像做云计算中给虚拟主机分配资源的呢。

你租的的是什么样的cpu,就最大给你这么大计算能力。
nkhanxh 2012-02-03

首先我觉得red提到的哪个方法肯定是可行的,其次我想讨论一下其他可能性:

似乎可以这样,修改linux线程调度。

首先记录下jvm进程的的id,然后就可以得知哪个线程是被哪个jvm创建的了。

然后就可以以jvm为单位控制线程起止了。

不过linux我不太熟,不知道这需要在哪个层次上进行修改。

当然如果修改jvm就最好了。在垃圾收集的full gc里面检查是否需要挂起。

在所有jvm上有个监管线程,如果有挂起需要就直接调用fullgc。

这样的好处是直接利用了safepoint,而不用造成什么性能损失。

RednaxelaFX 2012-02-04
nkhanxh 写道
似乎可以这样,修改linux线程调度。

你后面说的做法并没有修改Linux的线程调度

nkhanxh 写道
首先记录下jvm进程的的id,然后就可以得知哪个线程是被哪个jvm创建的了。

不用自己记录。HotSpot VM本身就有记。

nkhanxh 写道
然后就可以以jvm为单位控制线程起止了。

不过linux我不太熟,不知道这需要在哪个层次上进行修改。

当然如果修改jvm就最好了。在垃圾收集的full gc里面检查是否需要挂起。

在所有jvm上有个监管线程,如果有挂起需要就直接调用fullgc。

这样的好处是直接利用了safepoint,而不用造成什么性能损失。

这样做的坏处就是无法在通用的JVM上执行了。这是个tradeoff,不是所有人都肯付出自己维护VM的代价。

Oracle/Sun JDK和OpenJDK里的HotSpot VM当前的safepoint实际上是full safepoint,所有应用线程都要停下来,不用停的只有诸如VMThread、GCTaskThread之类。这样利用起来不太方便。Azul版的HotSpot VM的safepoint就可以指定只停部分线程,粒度细一些,倒确实是有可能经过一定改造暴露给Java层去控制。
nkhanxh 2012-02-04
感觉是我表达的问题。

“首先记录下jvm进程的的id”,在linux的创建进程的api里面处理,
具体怎么实现,我觉得只能采取一点猥琐的做法了,猥琐了之后估计应该可以识别出来哪个进程是jvm进程。


"然后就可以以jvm为单位控制线程起止了。"-->也是指在linux调度里面来做,应该是时钟中断吧,一定时间过去后,起一个调度任务,估计是什么tasklet之类的,应该不会直接放在时钟中断里面来做,因为时钟中断需要尽早返回吧。
然后在tasklet里面检查线程所属的进程号,如果是属于某个需要被暂停的jvm的,就挂起它。os这个级别挂起线程应该是很可靠的,不会有什么死锁之类的了。
这样好处是不需要熟悉jvm,但是坏处是改了linux,也等于需要定制linux了,是一个不太靠谱的方案,但我是想探讨一下可行性。


RednaxelaFX 写道
nkhanxh 写道
似乎可以这样,修改linux线程调度。

你后面说的做法并没有修改Linux的线程调度

nkhanxh 写道
首先记录下jvm进程的的id,然后就可以得知哪个线程是被哪个jvm创建的了。

不用自己记录。HotSpot VM本身就有记。

nkhanxh 写道
然后就可以以jvm为单位控制线程起止了。

不过linux我不太熟,不知道这需要在哪个层次上进行修改。

当然如果修改jvm就最好了。在垃圾收集的full gc里面检查是否需要挂起。

在所有jvm上有个监管线程,如果有挂起需要就直接调用fullgc。

这样的好处是直接利用了safepoint,而不用造成什么性能损失。

这样做的坏处就是无法在通用的JVM上执行了。这是个tradeoff,不是所有人都肯付出自己维护VM的代价。

Oracle/Sun JDK和OpenJDK里的HotSpot VM当前的safepoint实际上是full safepoint,所有应用线程都要停下来,不用停的只有诸如VMThread、GCTaskThread之类。这样利用起来不太方便。Azul版的HotSpot VM的safepoint就可以指定只停部分线程,粒度细一些,倒确实是有可能经过一定改造暴露给Java层去控制。

RednaxelaFX 2012-02-04
nkhanxh 写道
“首先记录下jvm进程的的id”,在linux的创建进程的api里面处理,
具体怎么实现,我觉得只能采取一点猥琐的做法了,猥琐了之后估计应该可以识别出来哪个进程是jvm进程。

一点也不用猥琐。即便在Linux层而不是在HotSpot VM层,这个也是现成的,啥额外的事情都不用做。你试试看ps找到一个Java进程的pid之后用top -H <pid>看看就明白了。

……中间省略……

nkhanxh 写道
这样好处是不需要熟悉jvm,但是坏处是改了linux,也等于需要定制linux了,是一个不太靠谱的方案,但我是想探讨一下可行性。

呵呵,那可能等你比较熟悉相关的一些实现之后,重新再来讨论这个话题会比较有意义。

修改OS或者是完全新写一个专用OS来跟JVM更好的配合,这种思路不是新事物,已经有现成的例子,只是在生产环境部署得不多,或许还没成为hype。你所想像的“可行性”主要取决是什么人为了什么目的去做,投入产出比有多少;纯技术说都是“可能”的。

讨论细节的话就得有足够背景知识,不讨论细节空打空的想像“可行性”就缺乏意义了。所以这里我会打住。
javas 2012-02-06
引用
拦截类加载,在类被真的加载之前改写里面的字节码,
1、找到所有循环末尾和方法结束(主要是正常返回,视情况看抛异常的地方是否也要包括)
2、在这些位置插入一些代码,检测一些你自己定义的条件,并在条件指定这个线程要暂停时自己调用wait()
3、另外写个类包装着这些条件。当需要恢复线程的执行时notify()它们


我赞同‘拦截’这个思路。
不过想到一个简单的方法,在系统启动时,设置应用的ThreadFactory,该ThreadFactory在生成Thread时,把传入的Runnable包装一下

1) time 的 instrument
2) 检测cpu占用情况,如果超过50%,则yield
RednaxelaFX 2012-02-06
javas 写道
我赞同‘拦截’这个思路。
不过想到一个简单的方法,在系统启动时,设置应用的ThreadFactory,该ThreadFactory在生成Thread时,把传入的Runnable包装一下

1) time 的 instrument
2) 检测cpu占用情况,如果超过50%,则yield

这个是如何简单?
在1)的instrument这步,你的提议是如何实现?
我觉得要真的起作用的话,最终实现出来的还得是一个java.lang.instrument系的agent,跟我之前说的一样。

光看外层的那个Runnable是没用的。假如代码是:
Runnable task = new Runnable() {
  private void foo() {
    while (true) { }
  }

  public void run() {
    foo();
  }
};

那么光看这个Runnable的run方法就不够用。而如果这个“foo”方法跟这个Runnable不在同一个类里,那么光看这个类也不够用。

这类字节码改写方式的限制,可以参考Kilim的状况。
javas 2012-02-06
上面解答不行,再给一个

1) thread cpu profiling
ThreadMXBean 中 getThreadCpuTime(long id) 可以得到线程的cpu运行时间
2) thread yield or stop
try priority
http://personals.ac.upc.edu/alonso/papers/RR212006.pdf
RednaxelaFX 2012-02-06
javas 写道
2) thread yield or stop

问题就是这一步如何实现。
只改priority是没保证的。如果要改priority可以在最初创建线程的时候就把priority设置到非常低,假如不在意它们饥饿。
michael9527 2012-02-06
RednaxelaFX 说的那个用java.lang.instrument去实现,老大说太耗性能了。

JPDA里面似乎有一个现成的,可以控制整个JVM挂起恢复的方法,
com.sun.jdi.VirtualMachine#suspend()
http://docs.oracle.com/javase/6/docs/jdk/api/jpda/jdi/index.html

这个问题说到底就是如何安全的停止,杀掉某个线程。
老大的意思是想在java语言级别去控制,不要弄的太底层。
太底层也没有那个技术底蕴,弄不出来。
Global site tag (gtag.js) - Google Analytics