美文网首页
Thread与ThreadLocal

Thread与ThreadLocal

作者: 叫我C30混凝土 | 来源:发表于2020-07-22 00:35 被阅读0次
    • Thread类的每一个实例代表一个JVM中的线程
      • 在Linux上称为'轻量级进程',和进程无本质区别,所以又统称为task即任务;(区别:仅仅是线程共享内存,而进程不共享内存),多个线程共享一份内存时,称为process group(进程组);
        以下代码为例:
    public class ThreadClass {
        static int i = 0;
    
        public static void main(String[] args) {
            new Thread(() -> {
                doSomething();
                return;
            }).start();
            doSomething();
        }
    
        private static void doSomething() {
            while (true) {
                i++;
            }
        }
    }
    
    代码Linux进程.jpg

    ↑↑↑Linux中线程也拥有独立的pid(jps查询java进程id,再用pstree查询该进程由哪些线程组成)

    • 在windows上使用系统线程

    优点:
    简单,直接依赖操作系统的调度器;
    缺点:
    占用资源多;每个JVM的线程都映射到Linux系统的内核线程,内核线程都有一套独立的方法栈,会占用空间;
    上下文切换慢;CPU切换不同任务时,每次都要发起不同的系统调用,并发起环境保存,下一次恢复的时候,还需要把环境从内存中取出;
    不灵活,无法实现灵活的优先级;JVM线程的调度非常依赖内核线程,没有办法灵活分配线程的占用资源或调整优先级;

    Thread的生命周期

    Thread生命周期.jpg

    代码地址:java.lang.Thread.State

    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.
             * 这个线程可能正在JVM执行,也可能在等待CPU资源/IO;
             * 等待IO过程: RUNNABLE发起IO状态--> Linux的open系统调用 
             *  -->CPU发现需要进行IO操作,就先去执行了其他操作,导致CPU虽然
             *  放弃该线程,但是线程依旧处于RUNNABLE状态;而当系统收到IO中
             *  断信号时,才去真正执行操作;(操作系统通过中断方式实现IO)
             *  虽然操作系统处于阻塞状态,但是在JVM眼中,依旧是RUNNABLE;
             */
            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}.
             * JVM中仅用来指代synchronized (锁)状态,
             * PS:monitor 称为监视器,synchronized 可以锁住一个monitor(当前对
             * 象或全局对象); 和操作系统中的阻塞状态没有任何关系;
             */
            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.
             * 
             * 如果对象Object被synchronized 锁住之后,其他人也想要用,就需要
             * 进入WAIT_QUEUE等待队列中;
             * 
             * WAITING 和 TIMED_WAITING仅指一堆线程等待一个对象的状态;
             * WAITING 和 TIMED_WAITING的区别,在于TIMED_WAITING有超 
             * 时操作Object#wait(long);
             * Object.wait(),notify()方法,是最初JVM设计中用于线程协同所用的状
             * 态;但是jdk1.5后设计了一套Lock和Condition来提供同样的功能;
             * 
             */
            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;
        }
    

    ThreadLocal

    • 当不同的线程共同调用heap(堆)中的同一个对象,希望不同线程返回不同结果,就需要使用ThreadLocal;
    • 通常用于储存线程私有的值,方便后续流程使用;
    java.lang.ThreadLocal
    /**
     * This class provides thread-local variables.  
    这个类提供线程局部变量
     * {@code ThreadLocal} instances are typically private
     * static fields in classes that wish to associate state with a thread (e.g.,
     * a user ID or Transaction ID).
    ThreadLocal实例通常是private static 变量,它能使每个线程拥有一个不同的状态;例如:user ID or Transaction ID;
    
    * <p>Each thread holds an implicit reference to its copy of a thread-local
     * variable as long as the thread is alive and the {@code ThreadLocal}
     * instance is accessible; after a thread goes away, all of its copies of
     * thread-local instances are subject to garbage collection (unless other
     * references to these copies exist).
    只要每个线程还活着,那么每一个线程都拥有一个隐式的拷贝;当一个线程结束,所有的拷贝都会被GC(除非还有其他地方引用这份拷贝);
    
    结论:所以在ThreadLocal代码中并没有map ,而是放在了Thread中;
     */
    

    ↑↑↑ThreadLocal代码注释

    public class ThreadClass {
        static MyThreadLocal threadLocal = new MyThreadLocal();
    
        public static void main(String[] args) {
            threadLocal.set("user2");
            new Thread(() -> {
                threadLocal.set("user1");
                doSomething();
            }).start();
            doSomething();
        }
    
        private static void doSomething() {
            System.out.println("thread:" + Thread.currentThread().getName() + ":" + threadLocal.get());
        }
        // 实现简易ThreadLocal
        private static class MyThreadLocal {
            //key:threadId,value:用户名
            Map<Long, String> map = new ConcurrentHashMap<>();
    
            public String get() {
                return map.get(Thread.currentThread().getId());
            }
    
            public void set(String userName) {
                map.put(Thread.currentThread().getId(), userName);
            }
        }
    }
    
    // 结果
    thread:main:user2
    thread:Thread-0:user1
    

    栈针

    栈针包含局部变量表与操作数栈,是执行字节码所需要的信息;

    相关文章

      网友评论

          本文标题:Thread与ThreadLocal

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