Java-多线程(六)细节

sleep方法和wait方法异同点是什么?

  • 相同点:可以让线程处于冻结状态。

  • 不同点:
    1,
    sleep必须指定时间。
    wait可以指定时间,也可以不指定时间。
    2,
    sleep时间到,线程处于临时阻塞或者运行。
    wait如果没有时间,必须要通过notify或者notifyAll唤醒。
    3,
    sleep不一定非要定义在同步中。
    wait必须定义在同步中。
    4,
    都定义在同步中,
    线程执行到sleep,释放执行权,不会释放锁。
    线程执行到wait,释放执行权,会释放锁。

synchronized(obj)
{
    //sleep(5000); //不释放锁
    wait();//0 1 2 线程wait
    code....
}
synchronized(obj)
{
    notifyAll();//唤醒3个wait,3个wait没有获取锁,临时阻塞状态。
    code....
        //释放锁 0 1 2其中有一个拿到锁
}

线程如何停止呢?

stop方法过时了,看起描述发现,有其他解决方案。
线程结束:就是让线程任务代码执行完,run方法结束。
run方法咋结束呢?
run方法中通常都定义循环,只要控制住循环就哦了。

注意:万一线程在任务中处于了冻结状态,那么它还能去判断标记吗?不能!
咋办?通过查阅stop方法的描述,发现提供了一个解决方法:
如果目标线程等待很长时间,则应使用 interrupt 方法来中断该等待
所谓的中断并不是停止线程。
interrupt的功能是 将线程的冻结状态清除,让线程恢复到的运行状态(让线程重新具备cpu的执行资格)。
因为时强制性的所以会有异常InterruptedException发生,可以在catch中捕获异常,
在异常处理中,改变标记让循环结束,让run方法结束。
//演示停止线程。
class Demo implements Runnable
{
    private boolean flag = true;
    public synchronized void run()
    {
        while(flag)
        {
            try
            {
                wait();//t1  t2
            }
            catch (InterruptedException e)
            {
                System.out.println(Thread.currentThread().toString()+"....."+e.toString());
                changeFlag();
            }

            System.out.println(Thread.currentThread().getName()+"----->");
        }
    }
    //对标记的修改方法。
    public void changeFlag()
    {
        flag = false;
    }
}


class StopThreadDemo 
{
    public static void main(String[] args) 
    {
        Demo d = new Demo();

        Thread t1 = new Thread(d,"旺财");
        Thread t2 = new Thread(d,"小强");
        t1.start();
        //将t2标记为后台线程,守护线程。
//      t2.setDaemon(true);
        t2.start();

        int x = 0;
        while(true)
        {
            if(++x == 50)//条件满足。
            {
//              d.changeFlag();//改变线程任务代码的标记,让其他线程也结束。
                //对t1线程对象进行中断状态的清除,强制让其恢复到运行状态。
                t1.interrupt();
                //对t2线程对象进行中断状态的清除,强制让其恢复到运行状态。
                t2.interrupt();

                break;//跳出循环,主线程可以结束。
            }
            System.out.println("main-------->"+x);
        }

        System.out.println("over");
    }
}

守护线程:也可以理解为后台线程,之前创建的都是前台线程。

只要线程调用了setDaemon(true);就可以把线程标记为守护线程。
前台后台线程运行时都是一样的,获取CPU的执行权执行。
只有结束的时候有些不同。
前台线程要通过run方法结束,线程结束。
后台线程也可以通过run方法结束,线程结束,还有另一种情况,
当进程中所有的前台线程都结束了,这时无论后台线程处于什么样的状态,都会结束,从而进程会结束。
进程结束依赖的都是前台线程。

线程的优先级:用数字标识的,1-10

其中默认的初始优先级时5 最明显的三个优先级 1,5,10。
setPriority(Thread.MAX_PRIORITY);
toString
class Demo implements Runnable
{
    private boolean flag = true;
    public synchronized void run()
    {
        while(flag)
        {
            try
            {
                wait();//t1  t2
            }
            catch (InterruptedException e)
            {
                System.out.println(Thread.currentThread().toString()+"....."+e.toString());
                changeFlag();
            }
        }
    }
    //对标记的修改方法。
    public void changeFlag()
    {
        flag = false;
    }
}

class StopThreadDemo 
{
    public static void main(String[] args) 
    {
        Demo d = new Demo();

        Thread t1 = new Thread(d,"旺财");
        Thread t2 = new Thread(d,"小强");
        t1.start();
        //将t2标记为后台线程,守护线程。
//      t2.setDaemon(true);
        t2.start();

        int x = 0;
        while(true)
        {
            if(++x == 50)//条件满足。
            {
//              d.changeFlag();//改变线程任务代码的标记,让其他线程也结束。
                //对t1线程对象进行中断状态的清除,强制让其恢复到运行状态。
                t1.interrupt();
                //对t2线程对象进行中断状态的清除,强制让其恢复到运行状态。
                t2.interrupt();

                break;//跳出循环,主线程可以结束。
            }
        }
    }
}
运行结果

线程组:ThreadGroup

可以通过Thread的构造函数明确新线程对象所属的线程组。
线程组的好处,可以对多个同组线程,进行统一的操作。
默认都属于main线程组。

join方法

class Demo implements Runnable
{

    public void run()
    {
        for(int x=1; x<=40; x++)
        {
            System.out.println(Thread.currentThread().getName()+"------>"+x);
        }
    }

}

class JoinThreadDemo 
{
    public static void main(String[] args) 
    {
        Demo d = new Demo();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);

        t1.start();
        t2.start();
        //主线程执行到这里,知道t1要加入执行,主线程释放了执行权,不管谁获得执行权,t1和t2都有可能获得执行权
        //执行资格并处于冻结状态,什么时候恢复呢?等t1线程执行完。
        try{t1.join();}catch(InterruptedException e){}//用于临时加入一个运算的线程。让该线程运算完,程序才会继续执行。
        for(int x=1; x<=50; x++)
        {
            System.out.println("main---------->"+x);
        }
        System.out.println("over");
    }
}

yield方法

线程临时暂停。将执行权释放,让其他线程有机会获取执行权

class Demo implements Runnable
{

    public void run()
    {
        for(int x=1; x<=40; x++)
        {
            System.out.println(Thread.currentThread().getName()+"------>"+x);
            Thread.yield();//线程临时暂停。将执行权释放,让其他线程有机会获取执行权。
        }
    }

}

class JoinThreadDemo 
{
    public static void main(String[] args) 
    {
        Demo d = new Demo();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);

        t1.start();
        t2.start();

        for(int x=1; x<=50; x++)
        {
            System.out.println("main---------->"+x);
        }
        System.out.println("over");
    }
}

线程的匿名内部类使用

        //第一种
        new Thread(){
            public void run(){
                for(int x=0; x<40; x++)
                {
                    System.out.println(Thread.currentThread().getName()+"...X...."+x);
                }
            }
        }.start();
        
        //第二种
        Runnable r= new Runnable(){
            public void run(){
                for(int x=0; x<40; x++)
                {
                    System.out.println(Thread.currentThread().getName()+"...Y...."+x);
                }
            }
        };
        new Thread(r).start();
  • 线程的匿名内部类的思考题

        new Thread(new Runnable()
        {
            public void run()
            {
                System.out.println("runnable run");
            }
        }){
            public void run()
            {
                System.out.println("subthread run");//执行。
            }
        }.start();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 该文章转自:http://blog.csdn.net/evankaka/article/details/44153...
    加来依蓝阅读 12,065评论 3 87
  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 8,054评论 1 18
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 7,180评论 1 15
  • 床前铺银丝,疑似外星光。 开户举头望,竟是破月荒。 万年此景遇,三生幸跳腔。 回首几所思,人生何足苍? 2011年4月书
    秋小羽1023阅读 1,092评论 0 0
  • 《今晚80后脱口秀》是我很喜欢的一档节目,喜欢它的诙谐搞笑和独特见解。 最近的节目中有一期主题是“燃”,一个很有正...
    點下阅读 4,576评论 0 2