美文网首页
Thread基础

Thread基础

作者: jellyliu57 | 来源:发表于2018-01-10 16:26 被阅读0次

    记录Java Thread的基础点。

    线程的实现

    线程的定义有两种方式

    • 继承Thread类
    • 实现Runnable接口

    线程的启动

    无论是继承Thread类还是实现Runnable接口,线程的启动方式都是:

    Thread thread = new Thread();
    thread.start();
    // 或者
    Thread runnable = new Thread(new Runnable());
    runnable.start();
    

    run()

    线程实际运行调用的是run()方法。

    • 其中Thread类中的run() 实际是调用传入Runnable对象的run()方法
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
    

    线程状态

    NEW, // 新建,创建后尚未启动的线程处于这种状态
    
    RUNNABLE, // 运行
              // 处于这种状态的线程有可能正在执行也有可能正在等待CPU分配执行时间
    
    BLOCKED, // 阻塞
    
    WAITING, // 无限期等待
             // 处于这种状态CPU不会分配执行时间
             // 需要其他线程唤醒
    
    TIMED_WAITING, // 限期等待
                   // 处于这种状态CPU不会分配执行时间
                   // 不需要其他线程唤醒,在一定时间之后会由系统自动唤醒
    
    TERMINATED; // 结束,线程已经结束执行
    

    线程状态转换关系图:


    java-thread-status.jpg

    线程的属性和方法

    设置优先级

    public final void setPriority(int newPriority)
    

    每个类都有自己的优先级,一般property用1-10的整数表示,默认优先级是5,优先级最高是10;优先级高的线程并不一定比优先级低的线程执行的机会高,只是执行的机率高;默认一个线程的优先级和创建他的线程优先级相同。

    sleep

    public static native void sleep(long millis) throws InterruptedException;
    public static void sleep(long millis, int nanos) throws InterruptedException
    

    可以使用TimeUnit的sleep方法

    TimeUnit.MILLISECONDS.sleep(500L);
    // 内部实现还是调用Thread.sleep()实现的,源码如下
    public void sleep(long timeout) throws InterruptedException {
        if (timeout > 0) {
            long ms = toMillis(timeout);
            int ns = excessNanos(timeout, ms);
            Thread.sleep(ms, ns);
        }
    }
    

    当前线程睡眠/millis的时间(millis指定睡眠时间是其最小的不执行时间,因为sleep(millis)休眠到达后,无法保证会被JVM立即调度);sleep()是一个静态方法(static method) ,所以他不会停止其他的线程也处于休眠状态;线程sleep()时不会失去拥有的对象锁。作用:保持对象锁,让出CPU,调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留一定的时间给其他线程执行的机会;

    yield

    public static native void yield();
    

    让出CPU的使用权,给其他线程执行机会、让同等优先权的线程运行(但并不保证当前线程会被JVM再次调度、使该线程重新进入Running状态),如果没有同等优先权的线程,那么yield()方法将不会起作用。

    它仅能是一个线程从运行状态转换到可运行状态,而不是等待或阻塞状态。

    join

    public final void join() throws InterruptedException
    
    public final synchronized void join(long mills)
        throws InterruptedException
    
    public final synchronized void join(long millis, int nanos) throws InterruptedException
    

    使用该方法的线程会在此之间执行完毕后再往下继续执行。

    特殊的线程方法

    object.wait()

    // 存在对象
    Object obj ;
    // 使用
    synchronized(obj){
        obj.wait(); // 无限等待
        obj.wait(1000L); // 设定等待超时时间(有限等待)
    }
    

    当一个线程执行到wait()方法时,他就进入到一个和该对象相关的等待池(Waiting Pool)中,同时失去了对象的机锁—暂时的,wait后还要返还对象锁。当前线程必须拥有当前对象的锁,如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常,所以wait()必须在synchronized 代码块中调用。

    object.notify()/notifyAll()

    唤醒在当前对象等待池中等待的第一个线程/所有线程。notify()/notifyAll()也必须拥有相同对象锁,否则也会抛出IllegalMonitorStateException异常。

    相关文章

      网友评论

          本文标题:Thread基础

          本文链接:https://www.haomeiwen.com/subject/uobonxtx.html