Java 如何使一个线程连接到另一个线程,但只等待n秒的CPU时间?
Java 如何使一个线程连接到另一个线程,但只等待n秒的CPU时间?,java,multithreading,unit-testing,concurrency,performance,Java,Multithreading,Unit Testing,Concurrency,Performance,otherThread.join(time)以毫秒为单位显示等待时间。我希望在实际CPU时间内等待时间,以便在应用程序中获得一致的行为 我已经快速查看了ThreadMXBean,但这似乎并不是我想要的(它告诉我线程的实际CPU时间,但没有提供等待一段时间过去的便捷方式)。围绕sleep()的繁忙循环可能会起作用,但似乎效率极低 我还考虑过使用另一个线程并等待一个条件,但我不确定这将如何工作。主线程将执行:myCondition.await(),其中另一个线程将在otherThread使用时间时切
otherThread.join(time)
以毫秒为单位显示等待时间。我希望在实际CPU时间内等待时间
,以便在应用程序中获得一致的行为
我已经快速查看了ThreadMXBean
,但这似乎并不是我想要的(它告诉我线程的实际CPU时间,但没有提供等待一段时间过去的便捷方式)。围绕sleep()
的繁忙循环可能会起作用,但似乎效率极低
我还考虑过使用另一个线程并等待一个条件
,但我不确定这将如何工作。主线程将执行:myCondition.await()
,其中另一个线程将在otherThread
使用时间时切换myCondition
。同样,这看起来很复杂,可能仍然需要控制线程有一个繁忙的循环
编辑:我这样做是为了评分脚本。这意味着,如果学生处于无限循环中,我需要有一种超时方法,并且需要公平。我一直在使用JUnit对学生进行测试,但这与超时有着相同的问题:如果同一个(低效的)提交被多次运行,它可能会得到不同的分数,这取决于当时机器上运行的其他作业(这对于小组工作来说是一个真正的问题)
但这也是普通单元测试的一个问题-通过使用时钟时间而不是CPU时间JUnit会得到不一致的测试结果?我建议一次运行一个JVM测试,并使用时间
(有关详细信息,请参阅)确定实际使用的CPU时间。如果时间太长的话就打断它。。。您可能可以使用shell脚本来完成这一点,或者只允许进程运行到完成,并根据实际花费的时间进行分级。我建议一次运行一个JVM测试,并使用时间
(有关详细信息,请参阅)来确定实际使用的CPU时间。如果时间太长的话就打断它。。。您可能可以使用shell脚本来完成这一点,或者只允许流程运行到完成,并根据实际花费的时间进行分级。不会发生。定时的join()
基于墙上的时钟时间,这意味着如果线程尚未退出,则可以设置硬件计时器以提供x秒后的异步中断。由于无法预先知道线程将使用多少CPU,因此无法在达到某个边界时安排中断。当一个进程自愿或强制地产生它的时间片时,CPU时间就被考虑进去了,所以无论如何也没有办法得到确切的数字
您能得到的最接近的结果是每隔一段时间轮询CPU利用率,并在超出限制的线程上调用interrupt()
。(仔细研究它的语义,因为中断线程不一定会立即停止线程。)如果您只关心线程是否占用了x秒以上的CPU时间,那么延迟检查得到的结果(如kx,其中k>1)就无关紧要了。它们仍然大于x,这足以让你知道你的候选人超过了极限
如果您在Unix-y系统上,可以做的一件事是将整个分配作为一个进程运行,并使用ulimit
将允许的CPU量限制在某个值上,并为JVM启动和程序加载添加合理的CPU量。不会发生。定时的join()
基于墙上的时钟时间,这意味着如果线程尚未退出,则可以设置硬件计时器以提供x秒后的异步中断。由于无法预先知道线程将使用多少CPU,因此无法在达到某个边界时安排中断。当一个进程自愿或强制地产生它的时间片时,CPU时间就被考虑进去了,所以无论如何也没有办法得到确切的数字
您能得到的最接近的结果是每隔一段时间轮询CPU利用率,并在超出限制的线程上调用interrupt()
。(仔细研究它的语义,因为中断线程不一定会立即停止线程。)如果您只关心线程是否占用了x秒以上的CPU时间,那么延迟检查得到的结果(如kx,其中k>1)就无关紧要了。它们仍然大于x,这足以让你知道你的候选人超过了极限
如果您在Unix-y系统上,您可以做的一件事是将整个分配作为一个进程运行,并使用ulimit
将允许的CPU量限制在某个值上,并为JVM启动和程序加载添加合理的CPU量。想想您的要求:您希望线程阻塞(而不是使用CPU时间)直到它使用了指定的CPU时间。这没有道理
我怀疑如果您的线程在另一个线程使用指定的CPU时间之前阻塞,您真正想要的是什么。这是不容易提供的,可能是因为它很少有用,可能会导致代码性能不佳。想想你的要求:你希望线程阻塞(不使用CPU时间),直到它使用了指定的CPU时间。这没有道理
我怀疑如果您的线程在另一个线程使用指定的CPU时间之前阻塞,您真正想要的是什么。这是不容易提供的,可能是因为它很少有用,可能会导致您的代码性能不佳。我认为如果您将thread.join()/interrupt()策略(用于超时错误代码(无限循环))和测试read calling back cpu time结合起来,您就会得到想要的结果,如果我不知道的话
public class GradingThread extends Thread {
private Thread testThread;
private long elapsedClockTime=-1;
public GradingThread(TestingThread testThread){
this.testThread = testThread;
testThread.setGradingThread(this);
}
public void setElapsed(long elapsedClockTime){
this.elapsedClockTime = elapsedClockTime;
}
public void run(){
System.out.println("GradingThread ID="+Thread.currentThread().getId());
try{
testThread.start();
testThread.join(5000);
testThread.interrupt();
}catch(Exception e){e.printStackTrace();}
if(elapsedClockTime==-1){
System.out.println("Student program timedout (more than 5000 clock seconds)");
}else{
System.out.println("Student program elapsed cpu time = "+(elapsedClockTime)/1000000+"ms");
}
}
public static void main(String[] args) {
(new GradingThread(new TestingThread())).start();
}
}
public class TestingThread extends Thread {
private GradingThread gradingThread;
public void setGradingThread(GradingThread thread){
gradingThread = thread;
}
public void run(){
StudentProgram sp = new StudentProgram();
System.out.println("TestingThrad ID="+Thread.currentThread().getId());
long scpu = getCpuTime();
sp.takeLessThan5WallSecondsToRun(); //try calling infiniteLoop() too.
long ecpu = getCpuTime();
gradingThread.setElapsed(ecpu - scpu);
}
/** Get CPU time in nanoseconds. */
public long getCpuTime( ) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
if ( ! bean.isCurrentThreadCpuTimeSupported())
return -1L;
long time = bean.getThreadCpuTime(Thread.currentThread().getId());
return time;
}
}//end of TestingThread.
class StudentProgram {
public void infiniteLoop(){
while(true);
}
public int takeLessThan5WallSecondsToRun(){
int total=0;
while(total < Integer.MAX_VALUE) total++;
return total;
}
}//end of StudentProgram.