Java 如何使N个可运行项在随机时间段内多次运行?
假设您有N个可运行对象,并且对于每个对象,您希望它们在随机时间段内执行。一旦一个可运行对象在该时间段内执行,您希望重新安排它在另一个随机时间段内运行。您希望能够多次为每个Runnable执行此操作 一旦启动runnable,它就应该在一个不确定的循环中执行某些操作——也就是说,runnable应该不知道它将运行多长时间。从runnable的角度来看,它将无限期地运行Java 如何使N个可运行项在随机时间段内多次运行?,java,concurrency,time,random,Java,Concurrency,Time,Random,假设您有N个可运行对象,并且对于每个对象,您希望它们在随机时间段内执行。一旦一个可运行对象在该时间段内执行,您希望重新安排它在另一个随机时间段内运行。您希望能够多次为每个Runnable执行此操作 一旦启动runnable,它就应该在一个不确定的循环中执行某些操作——也就是说,runnable应该不知道它将运行多长时间。从runnable的角度来看,它将无限期地运行 理想情况下,仅使用标准JavaAPI如何实现这一点?如果这不可能实现,那么最接近的替代设计是什么?。。你必须将a与a结合使用。我希
理想情况下,仅使用标准JavaAPI如何实现这一点?如果这不可能实现,那么最接近的替代设计是什么?。。你必须将a与a结合使用。我希望这是最后一期:) 您应该尝试以下方法:
public final class TaskManager
{
private Timer _timer;
private final ArrayList<Semaphore> _permits;
private final ExecutorService _threadPool;
public TaskManager(int numTasks)
{
_timer = new Timer()
_permits = new ArrayList<Semaphore>();
_threadPool = Executors.newFixedThreadPool(numTasks);
for(int i = 0; i < numTasks; ++i)
{
Semaphore available = new Semaphore(1);
_permits.add(available);
// execute the task
_threadPool.execute(new Runnable(){
public void run(){
// run the task
(new SampleTask(available)).run();
// schedule the task to be stopped after some delay
_timer.schedule(new TimerTask(){
public void run() {
// Stops the task
available.acquire();
}
}, /*SOME_RANDOM_DELAY*/;);
}
});
}
}
public void run()
{
while(true)
{
for(Semaphore available: _permits)
{
int delay = /*RANDOM_DELAY*/;
Semaphore permit = available;
// Allows the task to work
permit.release();
// Schedules when to stop the task
_timer.schedule(new TimerTask(){
public void run() {
// Stops the task
permit.acquire();
} }, delay);
// perhaps you should do something to ensure that you don't schedule the same permit twice...
}
}
}
}
public final class SampleTask extends Runnable {
private final Semaphore _available;
private final TaskManager _taskManager;
public SampleTask(Semaphore available)
{
_available= available;
}
// Implements the run method
public void run()
{
while(true)
{
// wait till I'm allowed to work
_available.acquire();
// pretend like I'm working
// release the semaphore when finished
_available.release();
}
}
}
公共最终类任务管理器
{
私人定时器;
私人最终ArrayList许可证;
私人最终执行人服务(线程池);
公共任务管理器(int numTasks)
{
_计时器=新计时器()
_许可证=新的ArrayList();
_threadPool=Executors.newFixedThreadPool(numTasks);
对于(int i=0;i
是的,我认为这是可能的。您只需将任务的截止日期保留在某个位置,然后使用计时器
,您只需检查给定的计时器任务
是否应继续运行或计时器是否应取消
这里有一个完整的例子。它远非完美,但只是它应该如何工作的概念证明
对于可运行的列表,您启动一个新的ExecuteTask
实例,该实例在内部知道它是否应该再次运行,或者它们是否已经到达死线
请注意,Runnables不知道它们是否会永远运行
在下面的代码中,我每秒钟重新安排一次,随机数在10秒范围内,但是你可以每毫秒重新安排一次,直到你认为合理的时间
例如:
Execute task = new ExecuteTask( new Runnable(){
public void run(){
System.out.println("Hi");
}
});
task.start(); // would run for "random" seconds....
我希望,我已经明白你需要什么了
import java.util.*;
import static java.lang.System.currentTimeMillis;
import static java.lang.System.out;
class ScheduledExecutionDemo {
public static void main( String [] args ) {
List<Runnable> runnables = Arrays.asList( new Runnable[]{
new Runnable(){ public void run(){ out.println("I'm the one");}},
new Runnable(){ public void run(){ out.println("I'm the two");}},
new Runnable(){ public void run(){ out.println("I'm the three");}},
new Runnable(){ public void run(){ out.println("I'm the four");}},
});
for( Runnable run : runnables ) {
new ExecuteTask( run ).start();
}
}
}
class ExecuteTask extends TimerTask {
// This map keeps track on when every task must finish.
// Every time a new instance is created it is stored here
// and every time it is scheduled again checks if it still have time.
private final static Map<Timer, Long> upTo = new HashMap<Timer, Long>();
private final static Random random = new Random();
private final Timer owner;
private final Runnable task;
public ExecuteTask( Runnable task ) {
this.owner = new Timer();
this.task = task;
upTo.put( owner, currentTimeMillis() + random.nextInt( 10 ) * 1000 );
}
public void start() {
owner.schedule( this, 0 , 1000 );
}
public void run() {
if( shouldRunAgain() ) {
task.run();
} else {
owner.cancel();
}
}
private boolean shouldRunAgain() {
return ExecuteTask.upTo.get( owner ) > currentTimeMillis();
}
}
import java.util.*;
导入静态java.lang.System.currentTimeMillis;
导入静态java.lang.System.out;
类ScheduledExecutionDemo{
公共静态void main(字符串[]args){
List runnables=Arrays.asList(新的Runnable[]{
new Runnable(){public void run(){out.println(“我就是那个”);},
new Runnable(){public void run(){out.println(“我是两个”);},
new Runnable(){public void run(){out.println(“我是三个”);},
new Runnable(){public void run(){out.println(“我是四个”);},
});
for(可运行运行运行:可运行){
新建ExecuteTask(run.start();
}
}
}
类ExecuteTask扩展了TimerTask{
//这张地图记录了每项任务必须完成的时间。
//每次创建新实例时,它都存储在这里
//每次它再次被安排时,都会检查它是否还有时间。
private final static Map up=new HashMap();
私有最终静态随机=新随机();
私人最终计时器所有者;
私有最终可运行任务;
公共执行任务(可运行任务){
this.owner=新计时器();
this.task=任务;
最大输入(所有者,currentTimeMillis()+随机.nextInt(10)*1000);
}
公开作废开始(){
业主一览表(本,0,1000);
}
公开募捐{
if(shouldrunreach()){
task.run();
}否则{
owner.cancel();
}
}
私有布尔值应再次运行(){
返回ExecuteTask.upTo.get(所有者)>currentTimeMillis();
}
}
有了这个概念证明,您可以使用队列,在可运行文件执行时将其放出来,在执行完成后将其放回去,而不是使用简单的列表
此外,可能存在一些同步问题,但根据您提供的信息,我认为这就足够了
我希望是他
ScheduledExecutorService ses = ...
Runnable runnable = ...
new RandomExecutor(ses, runnable, 10, 10);
new RandomExecutor(ses, runnable, 10, 10);
// run for a random length of time and wait for a random length of time, repeat.
public class RandomExecutor implements Runnable {
private static final Random rand = new Random();
private ScheduledExecutorService ses;
private Runnable runnable;
private int maxRun;
private int maxSleep;
public RandomExecutor(ScheduledExecutorService ses, Runnable runnable, int maxRun, int maxSleep) {
this.ses = ses;
this.runnable = runnable;
this.maxRun = maxRun;
this.maxSleep = maxSleep;
ses.execute(this);
}
@Override
public void run() {
long end = System.currentTimeMillis() + rand.nextInt(maxRun);
do {
runnable.run();
} while(end > System.currentTimeMillis());
ses.schedule(this, rand.nextInt(maxSleep)+1, TimeUnit.MILLISECONDS);
}
}