线程

创建方式

线程的创建有三种方式:继承Thread,实现Runnable接口,利用Callable跟Future

继承Thread

(1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
(2)创建Thread子类的实例,即创建了线程对象。
(3)调用线程对象的start()方法来启动该线程。

代码块

public class FirstMethod extends Thread {//Thread类的子类
        @Override
        public void run() {//重写该类的run方法
            super.run();  //线程要完成的任务
        }
    }
    FirstMethod firstMethod = new FirstMethod(); //创建Thread子类的实例,即创建了线程对象。
    firstMethod.start(); //调用线程对象的start()方法来启动该线程。
    
 

实现Runnable接口

  • (1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

  • (2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

  • (3)调用线程对象的start()方法来启动该线程。

代码块

public class SecondMethod implements Runnable{  //runnable接口的实现类,
        @Override
        public void run() {  //重写该接口的run()方法
             //线程的线程执行体
        }
    }
SecondMethod secondMethod=new SecondMethod();   //Runnable实现类的实例
new Thread(secondMethod).start(); //线程对象的start()方法来启动该线程
 

通过Callable跟FutureTask创建线程

1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
(3)使用FutureTask对象作为Thread对象的target创建并启动新线程。
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

代码块

public class ThirdMethod implements Callable<String> {  //Callable接口的实现类
        @Override
        public String call() throws Exception {  //实现call()方法
            return Thread.currentThread().getName();  //call()方法将作为线程执行体
        }
    }

   ThirdMethod thirdMethod=new ThirdMethod(); //Callable实现类的实例
   FutureTask<String> futureTask=new FutureTask<String>(thirdMethod);  //FutureTask类来包装Callable对象
        try {
            String threadName = futureTask.get();  //调用FutureTask对象的get()方法
​
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } 
    
 

 

对比分析

实现Runnable和实现Callable接口的方式基本相同,不过是后者执行call()方法有返回值,后者线程执行体run()方法无返回值,因此可以把这两种方式归为一种这种方式与继承Thread类的方法之间的差别如下:

1、接口创建线程可以实现资源共享,比如多个线程可以共享一个Runnable资源
2、但是编程稍微复杂,如果需要访问当前线程,必须调用Thread.currentThread()方法。
3、接口创建线可以避免由于Java的单继承特性而带来的局限。

 

成员变量:

代码块

// 线程名称
    private volatile String name;     
    // 线程优先级
    private int            priority;   
    private Thread         threadQ;
    private long           eetop;
​
    // 线程是否单步
    private boolean     single_step;   
​
    // 是否是守护线程   守护现场给主线程起辅助作用  当主线程死亡时,守护线程同时死亡
    private boolean     daemon = false;   
​
    /* JVM state */
    private boolean     stillborn = false;  //JVM state
​
    //从构造方法传过来的Runnable  也就是线程需要执行的任务
    private Runnable target;   
​
    //线程组
    private ThreadGroup group;   
​
    /* The context ClassLoader for this thread */
    //类加载器
    private ClassLoader contextClassLoader;    
​
    /* The inherited AccessControlContext of this thread */
    private AccessControlContext inheritedAccessControlContext;
​
    /* For autonumbering anonymous threads. */
    //线程编号
    private static int threadInitNumber;    
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
​
    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
     // 线程私有map
    ThreadLocal.ThreadLocalMap threadLocals = null;
​
    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
​
    /*
     * The requested stack size for this thread, or 0 if the creator did
     * not specify a stack size.  It is up to the VM to do whatever it
     * likes with this number; some VMs will ignore it.
     */
    //供给部分虚拟机使用的 成员变量
    private long stackSize;  
​
    /*
     * JVM-private state that persists after native thread termination.
     */
    private long nativeParkEventPointer;
​
    /*
     * Thread ID
     */
    private long tid;
​
    /* For generating thread ID */
    private static long threadSeqNumber;
​
    /* Java thread status for tools,
     * initialized to indicate thread 'not yet started'
     */
​
    private volatile int threadStatus = 0;        //初始状态
​
​
    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }
​
    /**
     * The argument supplied to the current call to
     * java.util.concurrent.locks.LockSupport.park.
     * Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
     * Accessed using java.util.concurrent.locks.LockSupport.getBlocker
     */
    volatile Object parkBlocker;
​
    /* The object in which this thread is blocked in an interruptible I/O
     * operation, if any.  The blocker's interrupt method should be invoked
     * after setting this thread's interrupt status.
     */
    private volatile Interruptible blocker;
    private final Object blockerLock = new Object();
​
    /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
     */
    void blockedOn(Interruptible b) {
        synchronized (blockerLock) {
            blocker = b;
        }
    }
​
    /**
     * 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;    //最高优先级
    
 


线程状态:

代码块

public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,
​
        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,
​
        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,
​
        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,
​
        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,
​
        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }
    
 

Thread 构造方法:

代码块

public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }
​
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
​
    Thread(Runnable target, AccessControlContext acc) {
        init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
    }
​
    public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
    }
​
    public Thread(String name) {
        init(null, null, name, 0);
    }
​
    public Thread(ThreadGroup group, String name) {
        init(group, null, name, 0);
    }
​
    public Thread(Runnable target, String name) {
        init(null, target, name, 0);
    }
​
    public Thread(ThreadGroup group, Runnable target, String name) {
        init(group, target, name, 0);
    }
​
    public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
        init(group, target, name, stackSize);
    }
线程的构造方法最终都调用了 init方法

代码块

    // 线程组 , 任务, 线程名字, 栈空间
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null, true);
    }
​
    /**
     * Initializes a Thread.
     *
     * @param g the Thread group
     * @param target the object whose run() method gets called
     * @param name the name of the new Thread
     * @param stackSize the desired stack size for the new thread, or
     *        zero to indicate that this parameter is to be ignored.
     * @param acc the AccessControlContext to inherit, or
     *            AccessController.getContext() if null
     * @param inheritThreadLocals if {@code true}, inherit initial values for
     *            inheritable thread-locals from the constructing thread
     */
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        //参数校验,线程name不能为null
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
        // 线程name 初始化
        this.name = name;
        //当前线程就是该线程的父线程
        Thread parent = currentThread();
        //获取系统的security
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */
​
            /* If there is a security manager, ask the security manager
               what to do. */
            //security不为null时,线程所在group为security的group
            if (security != null) {
                g = security.getThreadGroup();
            }
​
            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            //security为null时,直接使用父线程的group
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }
​
        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        g.checkAccess();
​
        /*
         * Do we have the required permissions?
         */
        //授权
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }
​
        g.addUnstarted();
​
        this.group = g;
        //将守护线程、优先级等设置为父线程的对应属性
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();  //设置优先级
        // 初始化contextClassLoader
        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 (inheritThreadLocals && 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 */
        //分配线程id
        tid = nextThreadID();
    }
    
 

 

启动线程其实做了这么几件事:

  1. 检查线程是否初始化;

  2. 通知group,线程启动;

  3. 调用native方法start0()启动线程,启动后执行run()方法;

  4. 启动失败容错处理。

 

代码块

public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */

        //假若当前线程初始化还未做好,不能start,0->NEW状态
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
​
        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        //通知group该线程即将启动,group的未启动线程数量减1
        group.add(this);
​
        boolean started = false;
        try {
            start0();  //本地方法,JVM调用target的run方法
            started = true;//更改启动标志
        } finally {
            try {
                //启动不成功,group设置当前线程启动失败
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            //执行target任务的run逻辑
            target.run();
        }
    }
    
 

synchronized 关键字说明start方法是同步的,并且是启动这个线程进行执行,JVM将会调用这个线程的run方法,这样产生的结果是,两个线程执行着,其中一个是调用start()方法的线程执行,另一个线程是执行run方法的线程。

 

sleep()方法:

 

代码块

public static native void sleep(long millis) throws InterruptedException;
​
    /**
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds plus the specified
     * number of nanoseconds, subject to the precision and accuracy of system
     * timers and schedulers. The thread does not lose ownership of any
     * monitors.
     *
     * @param  millis
     *         the length of time to sleep in milliseconds
     *
     * @param  nanos
     *         {@code 0-999999} additional nanoseconds to sleep
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative, or the value of
     *          {@code nanos} is not in the range {@code 0-999999}
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */

    //根据系统计时器和调度程序的精度和准确性,使当前正在执行的线程进入休眠状态(暂时停止执行)达指定的毫秒数加上指定的纳秒数。 该线程不会失去任何监视器的所有权。
    //不会释放锁等资源   释放cpu资源
    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) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }
​
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }
​
        sleep(millis);
    }
     

调用start()方法 初始化一些遍历 线程由初始状态 进入 就绪(ready)状态

就绪状态 抢占到cpu资源 转变为运行状态 被调用了stop() 方法 转为死亡状态

运行完毕 正常结束 由运行状态 转为 死亡状态 抛出异常 转为 死亡状态 调用了sleep() 方法 转为 sleeping状态 调用了wait() 方法 转为waiting 状态 被IO或同步代码块阻塞 转为阻塞状态

sleeping 状态 超时时间结束 转为 就绪(ready)状态

waiting 状态 被 notify() 或 notifyAll() 唤醒后 转为 就绪(ready)状态

阻塞状态 在IO完毕 或 进入同步代码块后 转为运行状态 被其他线程关闭IO Socket 后 转为死亡状态

 

 

线程中断方法

代码块

/**
     * Interrupts this thread.
     *
     * <p> Unless the current thread is interrupting itself, which is
     * always permitted, the {@link #checkAccess() checkAccess} method
     * of this thread is invoked, which may cause a {@link
     * SecurityException} to be thrown.
     *
     * <p> If this thread is blocked in an invocation of the {@link
     * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
     * Object#wait(long, int) wait(long, int)} methods of the {@link Object}
     * class, or of the {@link #join()}, {@link #join(long)}, {@link
     * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
     * methods of this class, then its interrupt status will be cleared and it
     * will receive an {@link InterruptedException}.
     *
     * <p> If this thread is blocked in an I/O operation upon an {@link
     * java.nio.channels.InterruptibleChannel InterruptibleChannel}
     * then the channel will be closed, the thread's interrupt
     * status will be set, and the thread will receive a {@link
     * java.nio.channels.ClosedByInterruptException}.
     *
     * <p> If this thread is blocked in a {@link java.nio.channels.Selector}
     * then the thread's interrupt status will be set and it will return
     * immediately from the selection operation, possibly with a non-zero
     * value, just as if the selector's {@link
     * java.nio.channels.Selector#wakeup wakeup} method were invoked.
     *
     * <p> If none of the previous conditions hold then this thread's interrupt
     * status will be set. </p>
     *
     * <p> Interrupting a thread that is not alive need not have any effect.
     *
     * @throws  SecurityException
     *          if the current thread cannot modify this thread
     *
     * @revised 6.0
     * @spec JSR-51
     */
     //中断指定thread对象线程
    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();
    }
​
    /**
     * Tests whether the current thread has been interrupted.  The
     * <i>interrupted status</i> of the thread is cleared by this method.  In
     * other words, if this method were to be called twice in succession, the
     * second call would return false (unless the current thread were
     * interrupted again, after the first call had cleared its interrupted
     * status and before the second call had examined it).
     *
     * <p>A thread interruption ignored because a thread was not alive
     * at the time of the interrupt will be reflected by this method
     * returning false.
     *
     * @return  <code>true</code> if the current thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see #isInterrupted()
     * @revised 6.0
     */
     //记录 当前线程被中断 标识
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }
​
    /**
     * Tests whether this thread has been interrupted.  The <i>interrupted
     * status</i> of the thread is unaffected by this method.
     *
     * <p>A thread interruption ignored because a thread was not alive
     * at the time of the interrupt will be reflected by this method
     * returning false.
     *
     * @return  <code>true</code> if this thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see     #interrupted()
     * @revised 6.0
     */
    public boolean isInterrupted() {
        return isInterrupted(false);
    }

    /**
     * Tests if some Thread has been interrupted.  The interrupted state
     * is reset or not based on the value of ClearInterrupted that is
     * passed.
     */
    private native boolean isInterrupted(boolean ClearInterrupted);
 

 

stop方法:

代码块

/**
     * Forces the thread to stop executing.
     * <p>
     * If there is a security manager installed, its <code>checkAccess</code>
     * method is called with <code>this</code>
     * as its argument. This may result in a
     * <code>SecurityException</code> being raised (in the current thread).
     * <p>
     * If this thread is different from the current thread (that is, the current
     * thread is trying to stop a thread other than itself), the
     * security manager's <code>checkPermission</code> method (with a
     * <code>RuntimePermission("stopThread")</code> argument) is called in
     * addition.
     * Again, this may result in throwing a
     * <code>SecurityException</code> (in the current thread).
     * <p>
     * The thread represented by this thread is forced to stop whatever
     * it is doing abnormally and to throw a newly created
     * <code>ThreadDeath</code> object as an exception.
     * <p>
     * It is permitted to stop a thread that has not yet been started.
     * If the thread is eventually started, it immediately terminates.
     * <p>
     * An application should not normally try to catch
     * <code>ThreadDeath</code> unless it must do some extraordinary
     * cleanup operation (note that the throwing of
     * <code>ThreadDeath</code> causes <code>finally</code> clauses of
     * <code>try</code> statements to be executed before the thread
     * officially dies).  If a <code>catch</code> clause catches a
     * <code>ThreadDeath</code> object, it is important to rethrow the
     * object so that the thread actually dies.
     * <p>
     * The top-level error handler that reacts to otherwise uncaught
     * exceptions does not print out a message or otherwise notify the
     * application if the uncaught exception is an instance of
     * <code>ThreadDeath</code>.
     *
     * @exception  SecurityException  if the current thread cannot
     *               modify this thread.
     * @see        #interrupt()
     * @see        #checkAccess()
     * @see        #run()
     * @see        #start()
     * @see        ThreadDeath
     * @see        ThreadGroup#uncaughtException(Thread,Throwable)
     * @see        SecurityManager#checkAccess(Thread)
     * @see        SecurityManager#checkPermission
     * @deprecated This method is inherently unsafe.  Stopping a thread with
     *       Thread.stop causes it to unlock all of the monitors that it
     *       has locked (as a natural consequence of the unchecked
     *       <code>ThreadDeath</code> exception propagating up the stack).  If
     *       any of the objects previously protected by these monitors were in
     *       an inconsistent state, the damaged objects become visible to
     *       other threads, potentially resulting in arbitrary behavior.  Many
     *       uses of <code>stop</code> should be replaced by code that simply
     *       modifies some variable to indicate that the target thread should
     *       stop running.  The target thread should check this variable
     *       regularly, and return from its run method in an orderly fashion
     *       if the variable indicates that it is to stop running.  If the
     *       target thread waits for long periods (on a condition variable,
     *       for example), the <code>interrupt</code> method should be used to
     *       interrupt the wait.
     *       For more information, see
     *       <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
     *       are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
     */
    @Deprecated
    public final void stop() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            checkAccess();
            if (this != Thread.currentThread()) {
                security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
            }
        }
        // A zero status value corresponds to "NEW", it can't change to
        // not-NEW because we hold the lock.
        if (threadStatus != 0) {
            resume(); // Wake up thread if it was suspended; no-op otherwise
        }
​
        // The VM can handle all thread states
        stop0(new ThreadDeath());
    }
 

能立刻杀死线程 缺点: 线程获取的锁 等资源不会释放 容易造成死锁等风险

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值