ctaskscheduler interface_hbase shell put

ctaskscheduler interface_hbase shell put这里记录下TaskScheduler的简单用法。使用场景:在使用Task的时候,大家都知道用TaskFactory.StartNew可以用来创建一个Task。这里如果创建10个,那么这10个Task就各自放飞直接运行了。一般情况下是没什么大问题,如果这10个中的每个Task非常耗CPU或者内存,而公司的产品又是非常考验配置成本(比如一体机,移动设备等),就需要让这10个Task按照一定要求执行,比如串行执行,从而节省资源、让机器还可以顺畅去干别的事情。Task...

这里记录下 TaskScheduler 的简单用法。

使用场景:

      使用 Task 的时候,大家知道用 TaskFactory.StartNew 可以用来创建一个 Task 。这里如果创建了 3 个,那么这3个 Task 就各自放飞直接运行了。

class Program
{
	private static TaskFactory _taskFactory;
	static void Main(string[] args)
	{
		_taskFactory = new TaskFactory();

		_taskFactory.StartNew(Func1);
		_taskFactory.StartNew(Func2);
		_taskFactory.StartNew(Func3);

		Console.ReadLine();
	}

	static void Func1()
	{
		Thread.Sleep(3000);
		Console.WriteLine("Func1");
	}
	static void Func2()
	{
		Thread.Sleep(2000);
		Console.WriteLine("Func2");
	}
	static void Func3()
	{
		Thread.Sleep(1000);
		Console.WriteLine("Func3");
	}
}
只听到从架构师办公室传来架构君的声音:
画堂人静雨蒙蒙,屏山半掩余香袅。有谁来对上联或下联?

结果:

Func3

Func2

Func1

一般情况下没什么大问题,但如果这3个中的每个Task都非常耗CPU或者内存,而计算机又需要预留资源去干别的事情,这就要让3个Task不能同时执行。又或者确实要让某些Task先做,有些后做。这就需要我们自己能够决定Task执行顺序。

怎样达到这样的效果?

答案就是:TaskScheduler,它可以让已经创建好的 Task 去按照特殊的顺序来执行。

就拿上面的场景来举例:

为了节约系统资源,我要让这3个Task单独执行,有一个在执行,其它俩就不能执行。最简单的就是串行执行,这样只需要写一个类继承TaskScheduler:

此代码由Java架构师必看网-架构君整理
public class MyTaskScheduler : TaskScheduler, IDisposable { private static readonly object _mutex = new object(); public readonly List<Task> _currentTasks = new List<Task>(); private readonly ManualResetEvent[] _schedulerEvents = new ManualResetEvent[2]; public override int MaximumConcurrencyLevel => 1; public MyTaskScheduler() { _schedulerEvents[0] = new ManualResetEvent(false); _schedulerEvents[1] = new ManualResetEvent(false); var executionThread = new Thread(ExecutionThread) { Name = "MyThread" }; executionThread.SetApartmentState(ApartmentState.MTA); executionThread.IsBackground = true; executionThread.Priority = ThreadPriority.Normal; executionThread.Start(null); } public void Dispose() { _schedulerEvents[1].Set(); } private void ExecutionThread(object args) { try { while (true) { if (!WaitIfEmpty()) { break; } Task task; lock (_mutex) { task = _currentTasks[0]; } try { TryExecuteTask(task); } catch (Exception) { throw; } finally { TryDequeue(task); } } } finally { //todo } } private bool WaitIfEmpty() { lock (_mutex) { if (_currentTasks.Count == 0) { //pause task _schedulerEvents[0].Reset(); } } //wait any signal. int id = WaitHandle.WaitAny(_schedulerEvents); // id is item index of _schedulerEvents return id == 0; } protected override IEnumerable<Task>? GetScheduledTasks() { lock (_mutex) { return _currentTasks.ToArray(); } } protected override void QueueTask(Task task) { lock (_mutex) { _currentTasks.Add(task); if (_currentTasks.Count > 0) { // Start task _schedulerEvents[0].Set(); } } } protected sealed override bool TryDequeue(Task task) { lock (_mutex) { var res = _currentTasks.Remove(task); return res; } } protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { return false; } }

主函数中只要稍作修改:

static void Main(string[] args)
{
	var taskScheduler = new MyTaskScheduler();
	_taskFactory = new TaskFactory(taskScheduler);

	_taskFactory.StartNew(Func1);
	_taskFactory.StartNew(Func2);
	_taskFactory.StartNew(Func3);

	Console.ReadLine();
}

运行结果:

Func1

Func2

Func3

在MyTaskScheduler 中,我建了一个线程 executionThread,线程方法是一个while循环,一直在监听有没有新的Task过来,有多个Task过来,就按Task创建顺序执行,没有的话 while 就暂停在 waitany 处。

这样的场景,配合 ManualResetEvent 和Task的CancellationTokenSource 非常适合做 带有暂停和取消功能的任务列表。

 

架构君码字不易,如需转载,请注明出处:https://javajgs.com/archives/211936
0
   

发表评论