java 线程 run和start方法,线程生命周期及join和yield方法,守护线程

  • 线程 run和start方法说明

run方法:其实是Runnable接口方法,只是个接口规范,业务逻辑都写在这个方法中(线程结束判断以及具体业务逻辑)

start方法:Thread 线程类封装的规范,一个线程实例只有调用了start方法,才能够开启新线程执行run。否则只调用run方法,实际并没有开启新的线程。start方法只能够调用一次,多次调用会报出异常 IllegalThreadStateException。start其实并不会开启线程,内部调用start0()方法才会真正的开启线程。

  • 线程生命周期

从这个图中可以看到线程的状态流转,这里主要介绍线程的join和yield方法,后续会详细讲解notify和wait方法。

join 方法(获取CPU执行权):a线程调用b线程的join方法,就是把当前CPU执行权交给线程b,当执行完b线程后,才执行线程a。一般会用来控制多线程按照顺序执行(本来多线程是并行执行的),通过join方法可以控制每个线程的执行顺序。

yield方法(奉献出CPU执行权):调用a线程的yield方法,线程a就会进入就绪状态,CPU会从就绪线程集合中随机(有优先级)拿一个线程执行。当然拿到的这个线程也可能还是a线程,yield方法跟锁没有任何关系,并不是说释放锁。

  • join方法案例,多任务按照顺序执行
  • 无序
import java.util.Random;

public class xu02 {
    private static class BuyTicket extends Thread{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"--正在购票--------");
            try {
                //模拟每个人购票时间不确定
                Thread.sleep(new Random().nextInt(50));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"--购票完成--------");
        }
    }
    public static void main(String[] args) {
        //创建3个人排队购票
        BuyTicket bird=new BuyTicket();
        bird.setName("bird");
        BuyTicket dog=new BuyTicket();
        dog.setName("dog");
        BuyTicket cat=new BuyTicket();
        cat.setName("cat");
        //1:无序购票(未排队),这里并不能够确定谁先买完票
        cat.start();
        dog.start();
        bird.start();
    }
}
  • 指定顺序购票
package com.hongying.multithread;

import java.util.Random;

public class xu02 {
    private static class BuyTicket extends Thread{
        private Thread preThread;//排在他前面的人
        public BuyTicket(Thread pre){
            this.preThread=pre;
        }
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"--正在购票--------");
            //做个判断,只有排在前面的人完成购票了才允许购票
            if(preThread!=null){
                try {
                    preThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            try {
                //模拟每个人购票时间不确定
                Thread.sleep(new Random().nextInt(50));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"--购票完成--------");
        }
    }
    public static void main(String[] args) {
        //创建3个人排队购票
        BuyTicket cat=new BuyTicket(null);//第一个位置
        cat.setName("cat");
        BuyTicket dog=new BuyTicket(cat);//第二个位置
        dog.setName("dog");
        BuyTicket bird=new BuyTicket(dog);//最后购票+
        bird.setName("bird");
        //有序购票,bird->dog->cat
        bird.start();//尽管bird第一个开启购票,但是也会是最后一个结束购票
        dog.start();
        cat.start();
        /*运行结果:
        * dog--正在购票--------
            *bird--正在购票--------
            cat--正在购票--------
            cat--购票完成--------
            dog--购票完成--------
            bird--购票完成--------
            */
    }
}
  • 守护线程和资源释放

守护线程:设置当前线程的setDaemon(true),默认创建线程是非守护线程;守护线程时,当主线程结束后,守护线程也跟着死亡。

资源释放:1、Object的finalize()方法,可以写资源释放,但是不推荐,有时不会执行。比如线程直接stop()

2、推荐 try-finally 资源释放,但是有个特列是当前线程是守护线程,主线程结束后,子线程如果不是interrupt 标志结束,子线程死亡有时不会调用finally 代码块。所以推荐不管是否是守护线程,线程结束都要使用 interrupt 标志 结束线程

代码案例:

package other.multithread;

/**
 * @ClassName DaemonTest
 * @Description des
 * @Author zyk
 * @Date 2019/9/26
 * @Version 1.0
 **/
public class DaemonTest {
    private static class DaemonThread extends Thread {
        @Override
        public void run() {
            try {
                while (true) {
                    System.out.println("-----------working...------------");
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("============线程结束==================");
                        break;
                    }
                }
            } finally {
                //通过finally 进行资源释放;如果是守护线程,线程结束finally有时还是不会执行
                System.out.println("=============finally-资源释放执行=============");
            }

        }

        @Override
        protected void finalize() throws Throwable {
            //Object finalize 方法,可以完成资源释放,但是线程停止则有可能不会调到finalize()
            System.out.println("=============finalize-资源释放执行=============");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        DaemonThread daemonThread = new DaemonThread();
        //设置守护进程后,开启线程的线程关闭后,守护线程也会结束;默认非守护线程
        daemonThread.setDaemon(true);
        daemonThread.start();

        Thread.sleep(20);
        //通过标志位暂停线程,如果不interrupt(),当前线程是守护线程,主线程结束子线程也跟着结束,此时finally中 资源释放有时就不会执行
        //daemonThread.interrupt();

        System.out.println("===========main线程结束=============");
    }
}
 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值