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

2020-07-27  本文已影响0人  TTLLong

线程脑图

多线程.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
    }
}
上一篇 下一篇

猜你喜欢

热点阅读