• 风动静泉
    2018-06-14
    一课一练:
    使用了两种方式获取当前程序的线程数。
    1、使用线程管理器MXBean
    2、直接通过线程组的activeCount
    第二种需要注意不断向上找父线程组,否则只能获取当前线程组,结果是1

    结论:
    使用以上两种方式获取的线程总数都是5个。
    main
    Attach Listener
    Signal Dispatcher
    Finalizer
    Reference Handler

    此外,如果使用的IDE是IDEA 直接运行会多一个Monitor Ctrl-break线程,这个是IDE的原因。debug模式下不会有这个线程。
    展开

    作者回复: 不错

     1
     62
  • 小文同学
    2018-06-14
    做了一个test分析老师的问题,观察到的情况如下:
    JVM 启动 Hello World的线程分析
    环境:
    macOS + jdk8
    检测获得
    Thread[Reference Handler,10,system]
    Thread[Finalizer,8,system]
    Thread[main,5,main]
    Thread[Signal Dispatcher,9,system]
    Hello World!
    其中:
    Reference Handler:处理引用对象本身的垃圾回收
    Finalizer:处理用户的Finalizer方法
    Signal Dispatcher:外部jvm命令的转发器

    在jdk6环境中
    还有一个Attach Listener的线程
    是负责接收外部命令的,如jmap、jstack

    展开

    作者回复: 不错

     2
     46
  • 行者
    2018-06-14
    “我们会发现一个特别的地方,通常幻象引用都会和引用队列配合清理机制使用,但是 ThreadLocal 是个例外,它并没有这么做。”
     老师,Entry继承的是WeakReference,这个是弱引用吧。
     main:
            System.out.println("hello world");
            ThreadGroup group = Thread.currentThread().getThreadGroup();
            ThreadGroup topGroup = group;
            while (group != null) {
                topGroup = group;
                group = group.getParent();
            }
            int nowThreads = topGroup.activeCount();
            Thread[] lstThreads = new Thread[nowThreads];
            topGroup.enumerate(lstThreads);
            for (int i = 0; i < nowThreads; i++) {
                System.out.println("线程number:" + i + " = " + lstThreads[i].getName());
            }
    out:
    线程number:0 = Reference Handler // 计算对象是否可达?
    线程number:1 = Finalizer // 回收对象时触发的finalize方法?
    线程number:2 = Signal Dispatcher // 线程调度员
    线程number:3 = main
    线程number:4 = Monitor Ctrl-Break // 监控器,锁相关
    展开

    作者回复: 前面是翻译窜了,已经修正;后面大家用了很多方法,基本都可以,主要目的是结合前面的介绍加深理解

    
     18
  • 爱折腾的老斑鸠
    2018-06-14
    theadlocal里面的值如果是线程池的线程里面设置的,当任务完成,线程归还线程池时,这个threadlocal里面的值是不是不会被回收?

    作者回复: 嗯,线程池一般不建议和thread local配合...

    
     12
  • 黄启航
    2018-07-09
    杨老师您好,我有个疑问:

    文章最后说"弱引用都会和引用队列配合清理工作,但是Threadlocal是个例外,它并没有这么做。这意味着,废弃项目的回收依赖显示地触发,否则就要等待线程的结束" 。

    我的疑问:既然没有利用引用队列来实现自动清除,那TheadLocalMap内部的Entry继承WeakReference有何用意?能起到什么作用?
    展开
     1
     8
  • 苦行僧
    2018-12-30
    边看老师的讲课 边反思工程代码
    
     5
  • 三木子
    2018-06-15
    现在觉得踩坑是一种很好学习方法

    作者回复: 同意

    
     5
  • tyson
    2018-06-14
    1、站在应用程序方面,只创建了一个线程。
    2、站在jvm方面,肯定还有gc等其余线程。

    总结:
    1、线程是系统调度的最小单元,应该是进程吧。线程是操作系统的资源,在运行的时候会打开文件描述符等。
    2、 resume、stop、suspend等已经被废弃了
    3、线程的等待和唤醒,建议使用reentrantlock的condition wait/notify方法
    4、可以使用线程的join方法、countdownlatch、cyclicbarrier、future等进行线程的等待
    展开

    作者回复: 不错

    
     5
  • TonyEasy
    2018-06-18
    老师,我有一点疑问,在线程池里复用线程时是不是对同一个线程调用了多次.start()方法呢?

    作者回复: 不是的,工作线程一般不退出的,复用的是类似runnable这种

    
     2
  • 锐
    2018-06-14
    通常弱引用都会和引用队列配合清理机制使用,但是 ThreadLocal 是个例外,它并没有这么做。

    这意味着,废弃项目的回收依赖于显式地触发,否则就要等待线程结束,进而回收相应 ThreadLocalMap!这就是很多 OOM 的来源

    这个平时还真没注意

    作者回复: 嗯,为了生命周期的需求

    
     2
  • 扬~
    2018-11-24
    等待与阻塞有什么区别呢

    作者回复: 范范谈有点晦涩,可以从线程进入、退出blocked/waiting的方法/条件来对比

    
     1
  • mongo
    2018-06-15
    杨老师请教你,关于高并发和线程池,我刚刚入门,工作中没有涉及过这一块。我阅读了oracle java tutorial high level concurrency 章节,阅读并粗略理解了《并发编程实践》这本书,想进一步清晰我的理解,我现在苦于在实践练习方面不知道怎么进行。老师有什么具体可行的思路指点一下吗?留言圈里有好多大神,在这里同时也请教其他的朋友。谢谢老师,谢谢大家。

    作者回复: 下面章节就会覆盖这部分,我谈下自己的思路:大部分工程师是没有机会在工作中,全面使用并发的那些东西的,尤其是反馈读者中初学者不少;所以,我建议有个整体性体系有个了解,分清大体都有什么;然后可以选些实践场景,去实现用例代码。面试中大体也就够了,毕竟项目经验不是教程能解决的

    
     1
  • sunlight001
    2018-06-14
    threadlocal在放入值之后,在get出来之后,需要做remove操作,我这么理解对么?以前写的程序都没remove😄

    作者回复: 不用了,明确移除是好习惯

    
     1
  • 食指可爱多
    2018-06-14
    我了解确定线程有:任务线程,Main线程,垃圾回收线程,还有些线程没细心关注名字和用途,惭愧了。可以在业务线程中等待,然后在命令行用jstack看看当前jvm的线程堆栈。

    作者回复: 其他就包括我们前面章节说过的finalizer,各种cleaner等,还有事件处理等

    
     1
  • Eason
    2018-06-14
    “比如,线程试图通过 synchronized 去获取某个锁,但是其他线程已经独占了,那么当前线程就会处于阻塞状态”这个例子换一个理解,感觉也是在等待其他线程做某些操作。在“阻塞”中也是在“等待”中??

    作者回复: wait和blocked是不同的

    
     1
  • jackLee
    2020-02-02
    /**
         * Causes this thread to begin execution; the Java Virtual Machine
         * calls the <code>run</code> method of this thread.
         * <p>
         * The result is that two threads are running concurrently: the
         * current thread (which returns from the call to the
         * <code>start</code> method) and the other thread (which executes its
         * <code>run</code> method).
         * <p>
         * It is never legal to start a thread more than once.
         * In particular, a thread may not be restarted once it has completed
         * execution.
         *
         * @exception IllegalThreadStateException if the thread was already
         * started.
         * @see #run()
         * @see #stop()
         */
        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".
             */
            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.add(this);

            boolean started = false;
            try {
                start0();
                started = true;
            } finally {
                try {
                    if (!started) {
                        group.threadStartFailed(this);
                    }
                } catch (Throwable ignore) {
                    /* do nothing. If start0 threw a Throwable then
                      it will be passed up the call stack */
                }
            }
        }
    展开
    
    
  • 天王
    2019-12-18
    17 一次线程多次调用start方法会提示IllegnalThreadStateException,1 线程生命周期的几个状态,在Java.lang.thread.state中,new线程刚创建还没真正启动的状态,runnable 就绪 表示该线程已经在jvm中执行,执行需要计算资源,可能正在运行,也可能正在等待cpu分配cpu片段,在就绪队列排队,blocked,阻塞 表示当前线程处于Monitor lock,比如线程试图获取某个锁,发现被其他线程占了,就会处于阻塞状态,等待waiting,比如生产者消费者模式,消费者条件未满足,让当前消费者等待,生产者去准备数据,通过notify等动作,通知消费者线程可以继续工作,计时等待,和进入等待的条件一样,调用方法是等待超时的方法,终止 terminated 不管意外退出还是自动终止,线程终止运行,也叫死亡,第二次调用start的时候,线程已经死亡或者处于非new的状态,所以会抛出异常 2 线程是什么 线程是线程调度的基本单元,一个进城包含多个线程,作为任务真正的执行者,有自己的栈,寄存器和本地存储等,但是会和进城中其他线程共享文件描述符和虚拟地址空间,线程分为内核线程和用户线程,看Thread的源码,以JNI形式调用的本地代码,3 创建线程 new Thread().start() thread.join(),线程的方法,有start,join等待线程结束,yield告诉调度室,主动让出CPU,基类Object提供了一些基础方法,wait,notify,notifyAll等方法,如果一个线程持有Minitor锁,会让其他线程处于wait状态,直到其他线程notify或者notifyall,Daemon Thread 守护线程,长期存在的服务线程
    展开
    
    
  • Geek_032104
    2019-11-19
    blocked和waiting除了等待的对象不一样(前者等待锁,后者等待其它线程),还有别的区别吗?
    
    
  • Paul Shan
    2019-11-11
    有了rxjava以后,真心不太想去直接写线程代码。
    
    
  • aof
    2019-10-06
    老师,线程等待时位于哪个区域?
    
    
我们在线,来聊聊吧