线程相关

Posted on By xqw

线程状态

  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,

        /** 等待获取锁 synchronized关键字
         * 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,

        /** 等待被其他线程notify
         * 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.sleep:Thread类的方法,必须带一个时间参数。会让当前线程休眠进入阻塞状态并释放CPU,提供其他线程运行的机会且不考虑优先级,但如果有同步锁则sleep不会释放锁即其他线程无法获得同步锁

2.yield:Thread类的方法,类似sleep但无法指定时间并且只会提供相同或更高优先级的线程运行的机会,不推荐使用

3.wait:Object类的方法,必须放在循环体和同步代码块中,执行该方法的线程会释放锁,进入线程等待池中等待被再次唤醒(notify随机唤醒,notifyAll全部唤醒,线程结束自动唤醒)即放入锁池中竞争同步锁

4.join:一种特殊的wait,当前运行线程调用另一个线程的join方法,当前线程进入阻塞状态直到另一个线程运行结束

利用interrupt()改变线程状态为中断(不用interrupt不能马上中断sleep wait等)
线程里sleep wait join会检测线程是否中断,中断则跑抛出InterruptException异常,线程finally里做终止最后的操作

wait/notify

调用wait进入waiting;被其他线程notify同时线程还没出synchronize代码块时则进入BLOCKED状态 wait和notify
1)将notify放在wait方法前面,那么线程t1就无法唤醒
2)wait和notify方法必须要在同步块或者方法里面,且成对出现使用

两个线程,一个有奇数一个有偶数,按顺序打印1到100;使用wait/notify

Condition.await()/signal()

1) await()方法一定要在signal()方法之前 2) Condition中的线程等待和唤醒方法之前,需要先获取锁

LockSupport.park/unpark

优点:
1.更简单,不需要获取锁,能直接阻塞线程。
2.更直观,以thread为操作对象更符合阻塞线程的直观定义;
3.更精确,可以准确地唤醒某一个线程(notify随机唤醒一个线程,notifyAll唤醒所有等待的线程);
4.更灵活 ,unpark方法可以在park方法前调用。
缺点:
1)因为标志位1,所以只能唤醒一次线程。连续park() unpark()没有效果。
LockSupport的用法及原理

public class SimpleThreads {  

    // Display a message, preceded by  
    // the name of the current thread  
    static void threadMessage(String message) {  
        String threadName =  
            Thread.currentThread().getName();  
        System.out.format("%s: %s%n",  
                          threadName,  
                          message);  
    }  

    private static class MessageLoop  
        implements Runnable {  
        public void run() {  
            String importantInfo[] = {  
                "Mares eat oats",  
                "Does eat oats",  
                "Little lambs eat ivy",  
                "A kid will eat ivy too"  
            };  
            try {  
                for (int i = 0;  
                     i < importantInfo.length;  
                     i++) {  
                    // Pause for 4 seconds  
                    Thread.sleep(4000);  
                    // Print a message  
                    threadMessage(importantInfo[i]);  
                }  
            } catch (InterruptedException e) {  
                threadMessage("I wasn't done!");  
            }  
        }  
    }  

    public static void main(String args[])  
        throws InterruptedException {  

        // Delay, in milliseconds before  
        // we interrupt MessageLoop  
        // thread (default one hour).  
        long patience = 1000 * 60 * 60;  

        // If command line argument  
        // present, gives patience  
        // in seconds.  
        if (args.length > 0) {  
            try {  
                patience = Long.parseLong(args[0]) * 1000;  
            } catch (NumberFormatException e) {  
                System.err.println("Argument must be an integer.");  
                System.exit(1);  
            }  
        }  

        threadMessage("Starting MessageLoop thread");  
        long startTime = System.currentTimeMillis();  
        Thread t = new Thread(new MessageLoop());  
        t.start();  

        threadMessage("Waiting for MessageLoop thread to finish");  
        // loop until MessageLoop  
        // thread exits  
        while (t.isAlive()) {  
            threadMessage("Still waiting...");  
            // Wait maximum of 1 second  
            // for MessageLoop thread  
            // to finish.  
            t.join(1000);  
            // 如果时间过长,则中断t线程
            if (((System.currentTimeMillis() - startTime) > patience)  
                  && t.isAlive()) {  
                threadMessage("Tired of waiting!");  
                t.interrupt();  
                // Shouldn't be long now  
                // -- wait indefinitely  
                t.join();  
            }  
        }  
        threadMessage("Finally!");  
    }  
}