05Thread类方法解析

Thread类方法解析

介绍

class Thread implements Runnable,Thread类继承Runnable,重写了run方法

1. 构造方法Thread(Runnable target)

接收一个Runnable类型的对象,赋值给Thread类属性private Runnable target;

2. start()/run()

start()是开启一个线程执行run()方法的内容,如果直接调用run()方法不会开启线程,只会执行run()方法的内容。

run方法源码:

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

默认情况下:如果target不为空,执行target.run(),也就是构造函数中的Runnable对象

    /**
     * 开启一个线程
     */
    @Test
    public void test01() {
        Thread thread = new Thread();
        //thread.run();//不能开启一个线程,是Runnable的接口的实现
        thread.start();
    }
    /**
     * 1.重写run方法
     *
     * @throws Exception
     */
    @Test
    public void test02() throws Exception {
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("my first thread");
            }
        };
        thread.start();
    }

3. stop()终止线程

stop()方法会强制把执行到一半的线程终止,可能会造成数据问题,不推荐使用

    @Test
    public void test04() {
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("my first thread");
            }
        };
        thread.stop(); //不推荐使用,直接中断线程
    }

4. 线程中断

线程中断是一种重要的线程协作机制,并不会立即使线程退出,而是设置一个中断标志,而如何处理,完全由线程自行决定。

与线程中断有关的有三个方法:

public void interrupt()    //中断线程,设置中断标志位
public boolean isInterrupted() //判断是否中断
public static boolean interrupted()  //判断是否中断,并清除当前中断状态

下面代码,设置中断标志,程序自己处理退出,若不处理中断,程序也会一直执行下去

    @Test    
	public void test05() throws Exception {
        Thread thread = new Thread(() -> {
            while (true) {
                //判断线程是否被中断
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("interruted");
                    break;
                }
                Thread.yield();
            }
        });
        thread.start();
        Thread.sleep(2000);
        //中断线程
        thread.interrupt();
        thread.join();
    }

5. sleep()

public static native void sleep(long millis)

sleep()方法可以设置让线程休眠若干时间,他会抛出一个InterruptedException异常,这个异常不是运行时异常,必须捕获。当线程sleep()时,如果中断,就会抛出这个异常。

sleep()方法由于中断而抛出异常,它会清除中断标记,故在异常处理中,若自己有捕获中断的逻辑,需要再次设置中断标志

    @Test
    public void test06() throws Exception {
        Thread thread = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("interruted");
                    break;
                }
                try {
                    System.out.println("1");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("interruted when sleep");
                    //设置中断状态,抛出中断后,这里会清除中断标记位
                    //所以线程不会停止,if判断一直为false
                    Thread.currentThread().interrupt();
                }
            }
        });
        thread.start();
        Thread.sleep(500);
        thread.interrupt();
        Thread.sleep(8000);
    }

6. wait()/notify()/notifyAll()

为了支持多线程之间协作,jdk提供了两个非常重要的方法wait()、notify(),这两个方法是Object类中的,也就是所有对象都可以调用。

如果一个线程调用了object.wait(),那么这个线程就会进入object对象的等待队列,这个队列中可能有多个线程,当object.nofity()调用时,会在等待队列中随机选择一个线程将其唤醒,这个选择是随机的。nofityAll()会唤醒等待队列中的所有线程。

object.wait()方法、notify()方法、notifyAll()方法必须在synchronized语句中,需要获得目标对象监视器。wait()方法执行后会释放监视器,wait()方法被唤醒后,还需要等待notify()所在的synchronized语句释放监视器,重新获得object的监视器后,才可以继续执行。

sleep()方法不会释放任何资源

@Test
    public void test12() throws Exception {
        Object object = new Object();

        Thread t1 = new Thread(() -> {
            synchronized (object) {
                System.out.println("t1 starting");
                try {
                    object.wait();//释放锁 等待唤醒 再获得锁,方可执行
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t1 end");
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (object) {
                System.out.println("t2 starting");
                object.notify();
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t2 end");
            }
        });

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

        /**
         * t1 starting
         * t2 starting
         * t2 end
         * t1 end
         */

        Thread.sleep(5000);
    }

7. suspend()/resume()

suspend()挂起线程,resume()继续执行,已经不推荐使用。

  1. suspend()在导致线程暂停的同时,并不会释放任何资源,这样会阻塞在相关锁上其它线程的执行
  2. 如果resume()意外在suspend()前就执行了,被挂起的线程就会一直挂起,锁也一直不会释放
  3. suspend()执行后被挂起的线程依旧是Runnable状态,这会严重影响我们对系统当前状态的判断
    @Test
    public void test07() throws Exception {
        Object o = new Object();
        Thread thread = new Thread(() -> {
            synchronized (o) {
                try {
                    Thread.sleep(2000);
                    Thread.currentThread().suspend();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });

        thread.start();
        //造成线程还没有暂停,就执行唤醒了,线程会一直暂停下去,不会终止
        //被锁住的资源也将会一直锁住
        thread.resume();
        thread.join();
    }

8. join()/yield()

线程之间协作的另一种方式

join()会一直阻塞在当前线程,知道目标线程完成,当然可以设置一个最大等待时间。join()的本质是调用线程的wait()方法,被调用线程在退出前会调用notifyAll()方法通知所有等待的线程。所以不要在Thread对象实例上调用wait()或者notify()等方法,可能会影响系统api工作

yeild()是让出当前cpu执行权,但是还会去争夺cpu资源,也就是还有可能再次抢到。

9. setPriority()

设置线程优先级1-10

jdk中默认设置了三种

	/**
     * The minimum priority that a thread can have.
     */
    public static final int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public static final int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public static final int MAX_PRIORITY = 10;

10. setDaemon()

设置是否为后台线程,线程分为后台线程与用户线程,

后台线程比如:垃圾回收线程,jit线程等

后台线程是为用户线程服务的,若用户线程执行完毕,后台线程也会死亡。

    @Test
    public void test09() throws Exception {
        Thread t = new Thread(() -> {
            try {
                while (true) {
                    System.out.println(1);
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t.setDaemon(true);
        t.start();
    }

实时内容请关注微信公众号,公众号与博客同时更新:程序员星星

实时内容请关注微信公众号,公众号与博客同时更新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值