代码改变世界

多线程编程(2)

2010-11-16 11:32  Clingingboy  阅读(735)  评论(2编辑  收藏  举报

 线程自身阻塞

   线程由于某些原因,可以停下一段时间即调用Sleep方法

妈妈给女儿削梨(Join)

1.妈妈削梨(thread1)
2.女儿吃梨(thread2)

必须先妈妈削梨,然后女儿才可以吃梨.即女儿在等待妈妈削梨这个动作结束,否则的话则停止吃梨.即线程2是依赖于线程1的.如下代码

此处调用了线程的Join方法,以等待该线程结束

public class Demo1
{
    private Thread thread2;
    private Thread thread1;
    public Demo1()
    {
        thread1 = new Thread(new ThreadStart(Task1));
        thread2 = new Thread(new ThreadStart(Task2));
        thread2.Start();
        thread1.Start();
    }

    public void Task1()
    {
        Console.WriteLine("削梨");
        Console.WriteLine(DateTime.Now);
        Thread.Sleep(5000);
    }

    public void Task2()
    {
        thread1.Join();
        Console.WriteLine(DateTime.Now);
        Console.WriteLine("吃梨");
    }
}

结果

image

Join有3个重载方法,如果线程1未结束,那么线程2那一直等待,可以设置一个时间,一直没反应的话则继续执行.

如果两个线程的任务是无关的,那么会运行的很好。一旦有了关系,则复杂度就出来了。

女儿改变想法不吃梨了(Interrupt)

如果妈妈削梨需要5分钟,而女儿只愿意等3分钟,3分钟过后就不要吃梨了,怪她娘削的太慢,然后让她娘别削了(做妈的真不容易)…
即线程2等了3分钟,若线程1还没完成任务,那么线程2就终止了线程1的操作

示例如下,Interrupt方法会中断处于WaitSleepJoin状态的线程,并抛出ThreadInterruptedException 异常

public void Task1()
{
    Console.WriteLine("妈妈开始削梨");
    try
    {
        Thread.Sleep(5000);
    }
    catch (ThreadInterruptedException e)
    {
        Console.WriteLine("妈妈停止削梨");
    }
}

public void Task2()
{
    var date1 = DateTime.Now;
    thread1.Join(3000);
    var date2 = DateTime.Now;
    if ((date2 - date1).TotalSeconds >= 3)
    {
        Console.WriteLine("女儿不吃梨了");
        thread1.Interrupt();
    }
    else
    {
        Console.WriteLine("吃梨");
    }
}

image

女儿突然不想吃梨了

上面的例子是考验耐性,
即线程在处于WaitSleepJoin的状态下,调用Interrupt来唤醒线程并中断
但妈妈是一直在削梨的,即这个线程是在做事的,不管梨有没削好,突然女儿就要吃梨了。。。即要将线程给中止掉.
示例如下
注意:这里线程2首先自身挂起3秒,跟线程1无关,其也不清楚线程1在干嘛,就是过了3秒突然想中止(Abort方法)线程1的任务
并非绝对的中止和中断:其是通过抛出异常来捕获中止和中断信息的,而非直接退出

public void Task1()
{
    Console.WriteLine("妈妈开始削梨");
    try
    {
        Thread.Sleep(5000);
    }
    catch (ThreadInterruptedException e)
    {
        Console.WriteLine("妈妈中断削梨");
    }
    catch (ThreadAbortException e)
    {
        Console.WriteLine("妈妈中止削梨");
    }
}

public void Task2()
{
    Thread.Sleep(3000);
    Console.WriteLine("女儿不吃梨了"); 
thread1.Abort(); }

中止以后:
当妈妈收到中止削梨的信号时,线程本身内部还可以做一些善后处理。比如女儿不吃自己吃微笑

当线程中止后,如果不调用ResetAbort方法,那么该线程catch之后的代码将无法继续执行.
如下示例

public void Task1()
{
    Console.WriteLine("妈妈开始削梨");
    try
    {
        Thread.Sleep(5000);
    }
    catch (ThreadInterruptedException e)
    {
        Console.WriteLine("妈妈中断削梨");
    }
    catch (ThreadAbortException e)
    {
        Console.WriteLine("妈妈中止削梨");
        Thread.ResetAbort();
    }
    Console.WriteLine("妈妈自己吃");
}

结果如下

image