美文网首页
Java线程总结 之 Java Thread的相关方法

Java线程总结 之 Java Thread的相关方法

作者: TTLLong | 来源:发表于2020-07-27 18:59 被阅读0次

    线程脑图

    多线程.png

    Thread相关

    创建线程的方法:
    1. 传Runnable方式。
    2. Thread子类
    3. 传FutureTask方式。
    
    1. Runnable方式:

    Runnable方式没有返回值。

    /**
     * @author jtl
     * @date 2019/10/11 17:03
     * Thread常见的3种创建方式:Runnable
     */
    public class ThreadDemo {
        public static void main(String[] args) {
            //Runnable
            Thread threadA=new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Thread is created with runnable");
                }
            },"ThreadA");
            threadA.start();
        }
    }
    
    1. Thread子类的方式:
    /**
     * @author jtl
     * @date 2019/10/11 17:03
     * Thread常见的3种创建方式:Thread子类
     */
    
    public class ThreadDemo {
        public static void main(String[] args) {
            ThreadC threadC=new ThreadC();
            threadC.setName("ThreadC");
            threadC.start();
        }
    
        private static class ThreadC extends Thread{
            @Override
            public void run() {
                super.run();
                 System.out.println("ThreadC name is: "+getName());
            }
        }
    }
    
    
    1. FutureTask方式:

    FutureTask:有返回值。在执行futureTask.get()方法时。会阻塞当前线程,直到futureTask所在子线程执行完,才会唤醒当前线程。

    /**
     * @author jtl
     * @date 2019/10/11 17:03
     * Thread常见的3种创建方式: FutureTask
     */
    
    public class ThreadDemo {
        public static void main(String[] args) {
            //FutureTask  callable
            Callable<String> callable=new Callable<String>() {
                @Override
                public String call() throws Exception {
                    Thread.sleep(1000);
                    return "Thread is created with callable";
                }
            };
            FutureTask<String> futureTask=new FutureTask<>(callable);
            Thread threadB=new Thread(futureTask,"ThreadB");
            threadB.start();
            try {
                long tt=System.currentTimeMillis();
                String msg=futureTask.get();
                // 在执行futureTask.get() 会阻塞当先线程,直到子线程执行完毕,才会唤醒主线程
                // 所以时间耗费为1000+ms
                System.out.println(msg+"---" +(System.currentTimeMillis()-tt));
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    
    线程的生命周期:
    1. 新建(New): 调用new方法,新建一个线程时,线程处于生命周期中的New。此时主要是为线程分配内存,初始化其成员变量。
    
    2. 就绪(Runnable):调用start方法,启动一个线程。此时JVM完成了栈和程序计数器的创建,等待该线程的调度和运行。
    
    3. 运行(Running):当处于Runnable的线程,被分配到CPU时间片后,线程开始执行run方法,此时处于运行状态。运行状态主要是执行run方法中的代码逻辑。
    
    4. 阻塞(Blocked):运行中的线程,主动或者被动的放弃CPU的使用权暂停运行。线程调用Object.wait()方法(等待阻塞),没有竞争到锁而阻塞(同步阻塞),线程调用Thread.sleep(),Thread
    .join()方法(其他阻塞)
    
    5. 死亡(Dead):线程运行结束,或者因为异常退出。
    
    线程的6种状态:
    1. NEW:线程被创建还没有运行(start)时的状态。
    
    2. RUNNABLE:线程在JAVA虚拟机运行时的状态。
    
    3. BLOCKED:线程被阻塞,因为运行synchronized的同步方法时,没有竞争到锁而被阻塞时的状态。
    
    4. WAITING:由于调用了Object.wait(),Thread.join(),LockSupport.park()等f非超时方法,导致线程处于等待状态,需要别的线程唤醒。
    
    5. TIMED_WAITING:由于调用了Thread.sleep,Object.wait(long),Thread.join(long),LockSupport.parkNanos(),LockSupport.parkUntil()等方法时线程处于的状态。它和WAITING状态不同之处在于。它设置了超时等待的时间,而WAITING状态没有。
    
    6. TERMINATED:线程已经退出时的状态。
    
       /**
         * A thread state.  A thread can be in one of the following states:
         * <ul>
         * <li>{@link #NEW}<br>
         *     A thread that has not yet started is in this state.
         *     </li>
         * <li>{@link #RUNNABLE}<br>
         *     A thread executing in the Java virtual machine is in this state.
         *     </li>
         * <li>{@link #BLOCKED}<br>
         *     A thread that is blocked waiting for a monitor lock
         *     is in this state.
         *     </li>
         * <li>{@link #WAITING}<br>
         *     A thread that is waiting indefinitely for another thread to
         *     perform a particular action is in this state.
         *     </li>
         * <li>{@link #TIMED_WAITING}<br>
         *     A thread that is waiting for another thread to perform an action
         *     for up to a specified waiting time is in this state.
         *     </li>
         * <li>{@link #TERMINATED}<br>
         *     A thread that has exited is in this state.
         *     </li>
         * </ul>
         *
         * <p>
         * A thread can be in only one state at a given point in time.
         * These states are virtual machine states which do not reflect
         * any operating system thread states.
         *
         * @since   1.5
         * @see #getState
         */
        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;
        }
    
    线程的常见方法
    1. Thread.sleep():当前线程休眠,此时线程让出cpu,进入TIMED-WATING状态。如果该线程竞争到了锁,在执行该方法时不会释放锁。等睡眠时间过后,重新竞争cpu。
    
    2. Thread.yield():让出CPU资源,和其他线程一起重新竞争CPU时间片。可能让出CPU之后,该线程会再次竞争到CPU。
    
    3. Thread.holdLock(Object):传入一个Object对象,返回bool值。当前线程是否持有该对象锁。
    
    4. join():当前执行该方法的线程进入WAITING状态。直到调用join方法的线程执行完毕或者别的线程调用interrupt方法报InterruptedException。Thread  a = new Thread(); a.join();原理是调用了线程实例a的wait方法。需强调,a.join(5000)只是让调用该方法的线程进入TIMED_WAITING状态,一旦过了5秒之后,执行改方法的线程将继续往下执行。
    
    5. setDaemon():设置该线程为守护线程。用户线程不全部退出,JVM不会退出。JVM退出,守护线程将死亡。
    
    6. setPriority():设置该线程的优先级,优先级高的线程在分配CPU资源的时候更有可能被优先分配。线程优先级在 Thread.MIN_PRIORITY(1) ~ Thread.MAX_PRIORITY(10) 之间。1最低,10最高。
    
    7. Thread.interrupted():返回某些线程是否已被中断。同时重置线程中断标记位。此时isInterrupted()返回为false。
    
    8. isInterrupted():测试某些线程是否已被中断。
    
    9. interrupt():当线程进入阻塞等待状态时,调用该方法会立刻报InterruptedException。退出BLOCKED或者WAITING状态。当线程为非阻塞状态,该方法会将Thread中的标志位设置为true,此时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 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 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);
        
        /**
         * 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
         */
        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();
        }
    
    sleep和wait方法的区别:
    1. sleep()是Thread的方法,调用该方法后,当前线程休眠,此时线程让出cpu,进入TIMED-WATING状态。执行该方法时不会释放锁。
    2. wait() 是Object的方法,调用该方法后,当前线程进入WAITING状态。此方法一般和synchronized一起使用,会释放锁。需要notify()/notifyAll()方法唤醒。
    
    线程结束的几种方法:
    1. 正常执行完逻辑代码。
    2. 线程阻塞时,调用thread.interrupt方法,捕获InterrutedException异常。
    3. 长时间循环运行的线程,用标记位来判断是否退出,具体看下方interrupt的示例代码
    4. stop方法:此方法已被废弃,不建议使用
    
    三个方法区别:isInterrupt(),interrupt(),Thread.interrupted()
    1. isInterrupt():只返回当前线程是否中断的标记位。
    2. Thread.interrupted():将标记位reset。此时再调用isInterrupt()返回的是false
    3. interrupt():阻塞状态时:捕获InterruptException异常
                    非阻塞状态时:将当前线程标记位,设置为true。
    

    ----------------------------非阻塞情况下的三种代码测试----------------------------

    /**
     * @author jtl
     * @date 2020/3/24 10:49
     * 非阻塞情况下的三种代码测试
     */
    
    class ThreadTest {
    
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    int count = 0;
                    //线程中断标记位为false。执行while循环
                    while (!Thread.currentThread().isInterrupted()) {
                        try {
                            if (count < 100) {
                                boolean a = Thread.currentThread().isInterrupted();
                                System.out.println("isInterrupted:" + a + "  " + count++);
                                Thread.sleep(50);
                            } else if (count>=100 && count<200){
                                boolean a = Thread.currentThread().isInterrupted();//标记位为:false
                                Thread.currentThread().interrupt();//标记位设置为:true
                                boolean b = Thread.currentThread().isInterrupted();
                                Thread.interrupted();//标记位reset,此时标记位为:false。所以循环不会退出
                                boolean c = Thread.currentThread().isInterrupted();
                                System.out.println("isInterrupted:before:" + a + "  isInterrupted:after:" + b + "  isInterrupted:after:" + c + "  " + count++);
                            }else{
                                boolean a = Thread.currentThread().isInterrupted();//标记位为:false
                                Thread.currentThread().interrupt();//标记位设置为:true。因为是非阻塞线程,所以不会捕获异常
                                boolean b = Thread.currentThread().isInterrupted();//标记位为:true
                                System.out.println("isInterrupted:before:" + a + "  isInterrupted:after:" + b + "  " + count++);
                                count = 0;
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            System.out.println("InterruptedException:"+ count + e.getMessage());
                            break;//退出循环
                        }
                    }
                }
            });
            thread.start();
            thread.join();//此处用join方法,wait住主线程,让主线程等待thread线程执行完毕
    
            System.out.println("join:" + " interrupted:" + thread.isInterrupted());
        }
    }
    

    ----------------------------阻塞情况下的执行interrupt方法测试----------------------------

    /**
     * @author jtl
     * @date 2020/3/24 10:49
     * 阻塞情况下的执行interrupt方法测试
     */
    
    class ThreadTest {
    
    
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("线程执行:sleep前");
                        //线程睡10秒
                        Thread.sleep(10000);
                        System.out.println("线程执行:sleep后");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        System.out.println("线程异常:"+e.getMessage());
                    }
                }
            });
            thread.start();
    
            Thread.sleep(1000);
            System.out.println("Thread标记位:"+thread.isInterrupted());//thread线程阻塞。此时标记位为默认的false
            thread.interrupt();//thread线程阻塞。执行interrupt()方法捕获异常
            System.out.println("Thread标记位:"+thread.isInterrupted());//thread线程。此时标记位为true
        }
    }
    

    相关文章

      网友评论

          本文标题:Java线程总结 之 Java Thread的相关方法

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