java并发-Thread类基本方法介绍

待更新
  1. java.lang.SecurityManager;
Thread中基本方法
1.void suspend()方法

  这是一个过时的方法,与void resume()搭配使用来暂停和唤醒一个线程。这两个方法有可能造成独占和不同步的问题—详见《java多线程编程核心技术》。方法源码如下:

    @Deprecated
    public final void suspend() {
        checkAccess();
        suspend0();
    }

  首先当前线程的checkAccess()方法被调用,其有可能导致SecurityException。如果当前线程时活跃着的,则挂起,调用resume()方法激活。相关方法checkAccess()和suspend0()源码如下:

/**
 *检测当前运行的线程是否有权限修改这个线程
 *    比如main线程使用代码someThread.suspend()来修改someThread线程;
 *如果有 安全管理器/SecurityManagy,则将被修改的线程作为参数调用安全管理器的    
 *checkAccess方法。
 *
 *如果当前线程没有权限修改被修改的线程,则抛出SecurityException异常。
 */
    public final void checkAccess() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkAccess(this);
        }
    }

  native指Java调用本地方法,通常为非java语言实现

    private native void suspend0();//原来源码名称后缀数字的是这个意思

  resume()方法同理,也是一个过时的唤醒线程的方法。如果当前线程没有权限修改被唤醒的线程,则抛出SecurityException异常
  

    @Deprecated
    public final void resume() {
        checkAccess();
        resume0();
    }
2.void yield()让当前线程暂时放弃cpu资源

  注意:线程放弃cup资源的时间是未知的,可能时间很长,也可能XX。这个方法是可以被scheduler忽略的。yield()是一个用来提高线程之间协作、避免线程过度使用cpu的启发性的尝试,应该小心使用。
  实际上,这个方法很少有机会使用,我们在debug或者测试的时候,yield()可能有助于我们处理由于“竞态条件(race conditions)”引起的bug,也有助与我们设计“并发控制结果concurrency control constructs”,比如java.util.concurrent.locks包中的AbstractQueued(Long)Synchronizer使用了这个方法。yield为native方法,源码如下
  

public static native void yield();
3.线程优先级

  线程优先级为1~10,数字越高代表级别越高优先级越高。Thread类中设置了三个默认的优先级属性:
  

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

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

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

当我们在使用void setPriority(int newPriority) 设置线程的优先级时,数字必须在这个区间。方法源码如下:

/**
 *final方法:不能被改写;final类不能被继承;
 *
 *
 *
 */
    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();//检查当前线程是否有修改此线程优先级的权限;
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {//优先级必须在[1,10]之间,否则抛异常:非法参数
            throw new IllegalArgumentException();
        }
        //fixme 返回被修改线程所在的线程组,如果被修改线程结束则返回null。如果要设置的值大于所在组线程的可以有的最大值,则自动降低为当前线程组已有的最大值。
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }

  这里有一个需要注意的点:如果要设置的值大于所在组线程的可以有的最大值,则自动降低为当前线程组已有的最大值。除此之外:
  1.线程具有继承性,即被创建的线程与其创建者具有相同的优先级;
  2.线程优先级即具有“规则性”,又具有“随机性”,即优先级高的线程有限执行,但其run()方法中任务又不一定是最先执行完。cup只是尽量将资源让给优先级比较高的线程,但是代码先运行、优先级高的线程不一定最先执行完。
  综上,线程的优先级具有1.组自贬性;2.继承性;3.随机性

4.守护进程:setDaemon(boolean )

  守护进程也可理解为“保姆进程”,当所需要服务的“雇主进程们”结束了,保姆进程自动销毁。最典型的守护进程是GC垃圾回收器。调用Thread 的setDaemon(boolean )方法传参true将进程设置为守护进程,此方法只能在start()调用之间调用,即进程为非存活的状态下。方法源码如下:

    public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {//如果当前线程已经通过start()方法激活,则不能在更改其类型。
            throw new IllegalThreadStateException();
        }
        daemon = on;//daemon是Thread类变量,标识其是否是守护进程
    }

[补充]:IDEA中变量上右键“Analyze”的子菜单下“Analyze Data Flow to/from Here”可以查看变量的引用情况。

五.停止线程

  强迫停止一个线程可以用Thread类的stop()方法,但是这个方法是不安全的,以被标记为deprecated。大多数情况下,停止一个线程使用interrupt()方法。
  除非线程要中断本身,否则操作总是被允许的。而且此操作只是为当前线程做标识“可以停止”,而非真正的停止线程。
  如果线程在调用wait()、join()、sleep()—等会,加入我们,睡觉及其各种变参多态函数后,再调用interrupt()方法会清空其interurpted的状态,并抛出InterruptedException异常。线程是否是“可停止状态”可以调用两个方法:
  1.boolean interrupted():会清除“可停止状态”,测试的是当前线程;
  2.boolean isInterrupted():不会清除状态,测试的是Thread对象;
看看源码我们即可知道这两个方法都调用了方法:

//参数表示返回其当前状态后是否将其重新设置为“不可停止”
private native boolean isInterrupted(boolean ClearInterrupted);

两个方法源码如下:

    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

    public boolean isInterrupted() {
        return isInterrupted(false);
    }

  停止线程书中讲解了三种方式:

  1. 异常法;
  2. 在沉睡中停止;
  3. 在这里不做讲解的stop()暴力停止;

异常法即当我们使用interrupted()(当前current线程)已经标记为“可停止”时,可以在run()方法中抛出异常并在run()方法的最后捕获异常,以此来停止线程。示例代码如下:

public DemoClass extends Thread{
    @Override
    public void run(){
        try{
            //doSomeThing
            if(this.interrupted()){
                throw new InterruptedException();
            }
        }catch(InterruptedException e){
            //doSomeThing
        }
    }
}

  正如我们上边讲的,如果线程调用wait()、join()、sleep()后再调用interrupt()方法,会清空停止状态并抛异常InterreptedException。使用这个方法也可以停止线程,其实与第一个差不多,我觉得。

六.获取线程id:long getId();
七.让线程休眠指定时间

  调用sleep(long million)或者sleep(long millis,int nans)可以使调用方法的线程休眠指定时间,方法可能抛出InterruptedException和IllegalArgumentException,源码如下:

//使当前线程休眠指定毫秒:1秒=1000毫秒
    public static native void sleep(long millis) throws InterruptedException;

/**
 *使线程休眠指定毫秒+纳秒,其实精确不了纳秒的级别:
 *  1.如果纳秒参数>500,000则休眠时间增加1毫秒(相当于向上取整);
 *  2.如果毫秒参数为0而且纳秒参数不为0,则休眠1毫秒;
 *  3.纳秒级别的参数不能超过1毫秒,即999,999;
 *  1ms=1000,000ns(纳秒)
 *
 **/
    public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {//纳秒级别的参数不能超过1毫秒
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }
八.检测线程是否“存活”

  方法源码如下,如果当前线程正在运行或者准备运行都会返回true

 public final native boolean isAlive();
九.返回当前正执行线程的引用
    public static native Thread currentThread();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值