Java教程

异步编程

本文主要是介绍异步编程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

从Thread说起

考虑到leetcode上一道题:使用异步编程,依次输出first,second,thrid

public class Foo
{
    bool syncFirst = true;
    bool syncSecond=false;
    bool syncThird=false;

    public Foo()
    {

    }

    public void First(Action printFirst)
    {

        // printFirst() outputs "first". Do not change or remove this line.
        while (true)
        {
            if (syncFirst)
            {
                printFirst();
                syncSecond = true;
                break;
            }
        }
    }

    public void Second(Action printSecond)
    {

        // printSecond() outputs "second". Do not change or remove this line.
        while (true)
        {
            if (syncSecond)
            {
                printSecond();
                syncThird = true;
                break;
            }
        }
        
    }

    public void Third(Action printThird)
    {

        // printThird() outputs "third". Do not change or remove this line.
        while (true)
        {
            if (syncThird)
            {
                printThird();
                break;
            }
        }
    }
}

上述代码是很传统的基于信号量的异步处理。

        var foo = new Foo();
        Action first = () =>
        {
            foo.First(() => Console.WriteLine("printing first"));
        };
        Action second = () =>
        {
            foo.Second(() => Console.WriteLine("printing second"));
        };
        Action third = () =>
        {
            foo.Third(() => Console.WriteLine("printing third"));
        };
        Thread t1 = new Thread(new ThreadStart(first));
        Thread t2 = new Thread(new ThreadStart(second));
        Thread t3 = new Thread(new ThreadStart(third));
        t1.Start();
        t2.Start();
        t3.Start();

main函数代码如上。
first等函数通过接受无参Action委托注入具体操作。死循环检查信号量,如果检测到就执行并退出。

Thread的初始化需要通过ThreadStart指定线程执行的任务,ThreadStart实际上是个无参Action委托。
通过Start来执行线程中的任务。

Console.WriteLine( t1.ThreadState.ToString()+t1.IsBackground);

查看线程状态,和是否为Background线程。
Background线程不同于Forground线程,进程如果没有后者将会被CLR直接杀死。

        t1.Suspend();
        t1.Resume();

除了Start还有悬停和重启。

C#中不建议使用Thread,因为创建线程需要消耗时间。

Parallel

相比Thread,编译器直接将 是否创建线程,使用哪个线程托管给了操作系统。Parallel本意为平行,使用其方法可以创造多个并行线程执行任务。

List<Action> a = new List<Action>();
for (int i = 0; i < 10; i++)
{
    var j = i;//非常重要,不然会闭包,所有的结果都是10。
    a.Add(new Action(() => Console.WriteLine($"Proceeding: {j}")));
}
Parallel.ForEach(a, i => i());
Console.WriteLine();
Parallel.For(0, 10, i => a[i]());

注意ForEach和For的不同:ForEach中的第一个参数是IEnumerable<T>接口,第二个参数是Action<T>
For中第一个参数是起始值,第二个参数类似于for语句中的i<10;第三个参数是Action<int>,和for语句非常类似。如果要在For语句循环时控制循环状态,例如:在循环到某个条件时停下,就要使用Action<int,ParallelLoopState>

lock

除了用信号量来解决异步问题,还可以用lock语句来锁住争抢资源。
信号量强调任务之间的协作关系,锁强调任务之间的争抢关系。信号量和锁可以并存,并不是互斥的。

这篇关于异步编程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!