java-并发-源码-Thread

一.线程的状态

创建(new)
就绪(runnable)
运行(running)
阻塞(blocked)
time waiting
waiting
消亡(dead)

创建之后不会立即就绪,需要等待资源分配
就绪后不会立即执行,需要等待分配到cpu时间才能执行,进入运行态
运行过程很多情况导致不能继续

  • 主动睡眠time waiting
  • 主动等待waiting
  • 被阻塞 blocked
    由于突然中断或者子任务执行完毕,线程就会被消亡

二. 上下文切换

单核CPU来说,一个时刻只能运行一个线程,如果运行另外一个线程叫做线程上下文切换;
上下文切换需要保存状态;
记录:程序计数器值,寄存器的状态;

三. 主要成员

    private volatile String name;
    private int            priority;
    private Thread         threadQ;
    private long           eetop;
    private boolean     single_step;        //是否要single_step
    private boolean     daemon = false;    
    private boolean     stillborn = false;     /* JVM state */
    private Runnable target;                /* What will be run. */
    private ThreadGroup group;                //ThreadGroup
    private ClassLoader contextClassLoader;    //上下文类加载器

    ThreadLocal.ThreadLocalMap threadLocals = null;
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

    private long stackSize;
    private long nativeParkEventPointer;
    private long tid;
    private static long threadSeqNumber;
    private volatile int threadStatus = 0;
    volatile Object parkBlocker;
    private volatile Interruptible blocker;
    private final Object blockerLock = new Object();

三. 常用方法

初始化
初始化方法都会调用init

  public Thread() {
       init(null, null, "Thread-" + nextThreadNum(), 0);
  }

进而调用

    init(g, target, name, stackSize, null);

代码如下

    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc) {
        ...
        this.name = name;
        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        //g是空的,因此执行这段代码,如果security不提供线程组,使用parent的线程组
        if (g == null) {    
            if (security != null) {
                g = security.getThreadGroup();
            }
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }
        //线程组检查权限
        g.checkAccess();
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }
        //线程组增加一个未启动的线程
        g.addUnstarted();
        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }

start方法
start创建的新线程会运行run方法

    public synchronized void start() {
        //刚创建的状态应该是0
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        //加入组
        group.add(this);
        boolean started = false;

        try {
            //调用本地方法start0()之后,开始运行,这里开始并发,这start0()会运行run方法
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

run方法

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

sleep方法
本地方法,调用系统的sleep函数

sleep(long millis)     //参数为毫秒
sleep(long millis,int nanoseconds)    //第一参数为毫秒,第二个参数为纳秒

sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。
但是sleep休眠并不会释放锁;

yeild方法
yield方法,让当前线程交出cpu权限,但是不释放锁,不能控制具体交出cpu的时间;
只能让相同优先级的线程获取cpu;
调用yield的线程重回就绪状态,重新等待cpu;

join方法

join()
join(long millis)
join(long millis,int nanoseconds)

在线程中调用thread1.join,那么这个线程会等待thread1执行完,或者等待时间;
代码如下,如果isAlive那么,会一直等待是否有信号唤醒

public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

wait让线程进入阻塞状态,释放锁,交出cpu执行权限

interrupt方法

结论如下:

  • 调用interrupt方法让阻塞状态的线程抛出异常;
  • interrup能直接中断阻塞的线程
  • 直接调用interrupt方法不能中断正在运行中的线程
  • interrupt方法和isInterrupted()方法停止正在运行的线程,这种中断是人为控制的

测试代码如下:

public class Test {
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread = test.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {  
        }
        thread.interrupt();
    } 
    class MyThread extends Thread{
        public void run() {
            int i = 0;
            while(!isInterrupted() && i<Integer.MAX_VALUE){
                System.out.println(i+" while循环");
                i++;
            }
        }
    }
}

interrupt代码如下

 public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

interrupt方法只是设置了标志位,并没有做其他的事情,每个Thread都有一个是否中断的标志位,这标志位是本地方法中的
isInterrupted()也是本地方法,判断这个标志位的状态

设置线程的中断,一般在Thread中增加一个标志位isStop,增加一个stop方法,代码如下:

	class MyThread extends Thread{
        private volatile boolean isStop = false;
        public void run() {
            int i = 0;
            while(!isStop){
                i++;
            }
        }
         
        public void setStop(boolean stop){
            this.isStop = stop;
        }
    }

stop和destroy是不安全的方法,已经被废弃

线程属性方法

getId					//用来得到线程ID
getName和setName			//用来得到或者设置线程名称。
getPriority和setPriority	//用来获取和设置线程优先级。
etDaemon和isDaemon		
currentThread()

守护线程
守护线程和用户线程的区别在于:
守护线程依赖于创建它的线程,而用户线程则不依赖。
举个简单的例子:如果在main线程中创建了一个守护线程,当main方法运行完毕之后,守护线程也会随着消亡。
而用户线程则不会,用户线程会一直运行直到其运行完毕。在JVM中,像垃圾收集器线程就是守护线程。

http://www.jb51.net/article/32372.htm

posted @ 2016-09-13 22:16  zhangshihai1232  阅读(139)  评论(0)    收藏  举报