码迷,mamicode.com
首页 > 编程语言 > 详细

黑马程序员_日记19_Java多线程(九)

时间:2015-04-02 09:14:27      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:停止线程   守护线程   join   yield   线程组和优先级   

 ——- android培训java培训、期待与您交流! ———-

1 停止线程

原理:让run方法结束。而run方法中通常定义循环结构,所以就是控制住循环结构就可以了。

stop方法已经过时了。

如何控制循环结构??
1 定义结束标记
2 当线程处于了冻结状态,没有执行标记,程序一样无法结束。
这时可以循环,正常退出冻结状态,或者强制结束冻结状态。
强制结束冻结状态:interrupt();目的是线程强制从冻结状态恢复到运行状态。
但是会发生InterruptedException异常。

//1 定义结束标记结束线程
class StopThread implements Runnable
{
    boolean flag = true;//定义标记控制循环结构

    //覆盖run方法
    public void run()
    {
        while(flag)
        {
            System.out.println(Thread.currentThread().getName()+"...run");//打印调用run方法的线程名
        }
    }

    //改变标记
    public void changeFlag()
    {
        flag = false;
    }
}


class StopThreadDemo
{
    public static void main(String[] args) 
    {
        StopThread st = new StopThread();//建立实现了Runnable接口的类的对象
        Thread t1 = new Thread(st);//建立线程1
        Thread t2 = new Thread(st);//建立线程2
        t1.start();//启动线程1,调用run方法
        t2.start();//启动线程2,调用run方法

        //定义一个循环,等线程1和线程2运行一会儿之后,主线程再把标记flag改为false
        int num = 0;
        while(true)
        {
            if(num++ == 50)
            {
                st.changeFlag();//改变run方法中while循环的标记
                break;//改变标记后,立刻结束主线程的while循环
            }
            System.out.println(Thread.currentThread().getName()+"......run"+num);//展示主线程执行的结果
        }
        System.out.println("over");//表示主线程执行完毕
    }
}

部分运行结果:
Thread-0…run
Thread-0…run
Thread-1…run
Thread-0…run
main……run50
Thread-0…run
Thread-1…run
over

从控制台中,可以看到,当主线程运行while循环50次后,
就从while循环中跳出来,并执行结束了。
而且线程1和线程也结束了。

下面看一下当线程处于冻结状态时候如何结束线程

class StopThread implements Runnable
{
    boolean flag = true;//定义标记控制循环结构

    //覆盖run方法,注意只有在同步中才可以使用wait
    public synchronized void run()
    {
        while(flag)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e)
            {
                System.out.println(Thread.currentThread().getName()+"...异常");
                flag = false;//中断线程的冻结状态后,立即改变标记,结束循环,结束run,结束线程
            }
            System.out.println(Thread.currentThread().getName()+"...run");//打印调用run方法的线程名
        }
    }
}


class StopThreadDemo
{
    public static void main(String[] args) 
    {
        StopThread st = new StopThread();//建立实现了Runnable接口的类的对象
        Thread t1 = new Thread(st);//建立线程1
        Thread t2 = new Thread(st);//建立线程2
        t1.start();//启动线程1,调用run方法
        t2.start();//启动线程2,调用run方法

        //定义一个循环,等线程1和线程2运行一会儿之后,主线程再把标记flag改为false
        int num = 0;
        while(true)
        {
            if(num++ == 50)
            {   
                t1.interrupt();//强制清楚线程1的冻结状态
                t2.interrupt();//强制清楚线程1的冻结状态
                break;//改变标记后,立刻结束主线程的while循环
            }
            System.out.println(Thread.currentThread().getName()+"......run"+num);//展示主线程执行的结果
        }
        System.out.println("over");//表示主线程执行完毕
    }
}

在把run方法改为下面这样的时候

public synchronized void run()
    {
        while(flag)
        {
            try
            {
                this.wait();
            }
            catch (InterruptedException e)
            {
            }
            System.out.println(Thread.currentThread().getName()+"...run");//打印调用run方法的线程名
        }
    }

运行结果显示:
线程1和线程2一调用run方法就陷入冻结状态。
而且,直到主线程结束,它们也没有结束。

对此,我们利用interrupt方法来强制中断线程的冻结状态。

总结:
特殊情况:
当线程处于了冻结状态。
就不会读取到标记。那么线程就不会结束。

当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。

Thread类提供该方法 interrupt();

2 线程中一些常见的方法

2.1 守护线程

setDaemon(boolean):将线程标记为后台线程,后台线程和前台线程一样,开启,一样抢执行权运行,
只有在结束时,有区别,当前台线程都运行结束后,后台线程会自动结束。
把前面结束线程的例子改动一下。

class StopThread implements Runnable
{
    boolean flag = true;//定义标记控制循环结构

    //覆盖run方法,
    public void run()
    {
        while(flag)
            System.out.println(Thread.currentThread().getName()+"...run");//打印调用run方法的线程名
    }
}


class StopThreadDemo
{
    public static void main(String[] args) 
    {
        StopThread st = new StopThread();//建立实现了Runnable接口的类的对象
        Thread t1 = new Thread(st);//建立线程1
        Thread t2 = new Thread(st);//建立线程2
        t1.setDaemon(true);//标记线程1为后台线程
        t2.setDaemon(true);//标记线程2为后台线程
        t1.start();//启动线程1,调用run方法
        t2.start();//启动线程2,调用run方法

        //定义一个循环,等线程1和线程2运行一会儿之后,主线程再把标记flag改为false
        int num = 0;
        while(true)
        {
            if(num++ == 50)
            {   
                break;//改变标记后,立刻结束主线程的while循环
            }
            System.out.println(Thread.currentThread().getName()+"......run"+num);//展示主线程执行的结果
        }
        System.out.println("over");//表示主线程执行完毕
    }
}

运行结果
Thread-0…run
Thread-1…run
main……run50
Thread-1…run
Thread-0…run
Thread-1…run
over
Thread-1…run
结果显示:当主线程结束之后,线程1和线程2立刻结束了

2.2 join方法

join方法:抢夺CPU执行权,直到该线程执行结束,才放弃CPU执行权。
例如,当主线程碰到t1.join()时,主线程就挂起,让出CPU给线程t1,
当线程t1结束后,主线程才重新启动。
示例如下。

class Join implements Runnable
{
    public void run()
    {
        for(int i =0;i < 50; i++)
            {
            System.out.println(Thread.currentThread().toString()+"is running..."+i);
            Thread.yield();
            }
    }
}
class JoinDemo 
{
    public static void main(String[] args)throws InterruptedException
    {
        Join j =new Join();
        Thread t1 = new Thread(j);
        Thread t2 = new Thread(j);
        //t1.setPriority(Thread.MIN_PRIORITY);
        t1.start();
        //t1.setPriority(Thread.MAX_PRIORITY);
        //t1.join();//线程t1调用Join方法,观察main打印结果
        t2.start();

        /*
        for(int i = 0;i < 60; i++)
            System.out.println(Thread.currentThread().getName()+"is running............"+i);*/
        System.out.println("over");
    }
}

运行结果显示,当线程t1运行完毕之后,才开始执行t2和主线程。

小结:
join():什么意思?等待该线程结束。当A线程执行到了B的.join方法时,A就会处于冻结状态。
A什么时候运行呢?当B运行结束后,A就会具备运行资格,继续运行。加入线程,可以完成对某个线程的临时加入执行。

2.3 yield方法

yield:临时暂停,可以让线程是释放执行权。
在run方法里面添加Thread.yield();
结果为:
Thread[Thread-0,5,main]is running…0
Thread[Thread-1,5,main]is running…1
Thread[Thread-0,5,main]is running…1
Thread[Thread-0,5,main]is running…2
Thread[Thread-0,5,main]is running…3
Thread[Thread-1,5,main]is running…2
Thread[Thread-0,5,main]is running…4
Thread[Thread-1,5,main]is running…3
Thread[Thread-0,5,main]is running…5
Thread[Thread-1,5,main]is running…4
Thread[Thread-0,5,main]is running…6
Thread[Thread-1,5,main]is running…5
两线程在交替执行。

yield()达到了平均分配CPU的效果

3 线程组和优先级

线程组:谁开启就属于谁。样例如下:
Thread[Thread-0,10,main]is running…49
Thread[Thread-1,5,main]is running…49
默认优先级为5,只有1,5,10最明显

public static final int MIN_PRIORITY = 1;
public static final int MAX_PRIORITY = 10;
public static final int NORM_PRIORITY = 1;

4 wait和sleep的区别

wait和sleep的区别:
wait:释放cpu执行权,释放同步中锁。
sleep:释放cpu执行权,不释放同步中锁。

黑马程序员_日记19_Java多线程(九)

标签:停止线程   守护线程   join   yield   线程组和优先级   

原文地址:http://blog.csdn.net/itheima_1llt/article/details/44814711

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!