Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使N个可运行项在随机时间段内多次运行?_Java_Concurrency_Time_Random - Fatal编程技术网

Java 如何使N个可运行项在随机时间段内多次运行?

Java 如何使N个可运行项在随机时间段内多次运行?,java,concurrency,time,random,Java,Concurrency,Time,Random,假设您有N个可运行对象,并且对于每个对象,您希望它们在随机时间段内执行。一旦一个可运行对象在该时间段内执行,您希望重新安排它在另一个随机时间段内运行。您希望能够多次为每个Runnable执行此操作 一旦启动runnable,它就应该在一个不确定的循环中执行某些操作——也就是说,runnable应该不知道它将运行多长时间。从runnable的角度来看,它将无限期地运行 理想情况下,仅使用标准JavaAPI如何实现这一点?如果这不可能实现,那么最接近的替代设计是什么?。。你必须将a与a结合使用。我希

假设您有N个可运行对象,并且对于每个对象,您希望它们在随机时间段内执行。一旦一个可运行对象在该时间段内执行,您希望重新安排它在另一个随机时间段内运行。您希望能够多次为每个Runnable执行此操作

一旦启动runnable,它就应该在一个不确定的循环中执行某些操作——也就是说,runnable应该不知道它将运行多长时间。从runnable的角度来看,它将无限期地运行


理想情况下,仅使用标准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);
    }
}