java--浅谈线程(一简单介绍)

一、线程基础:

1.CPU核心数和线程数的关系

线程数:是同一时刻设备能并行执行的程序个数,线程数=cpu个数 * 核数,及程数=cpu个数(2) * 核数(2)=4;

使用了超线程技术后---> 1:2

 

2.cpu线程数和Java多线程

 

(1) 线程是CPU级别的,单个线程同时只能在单个cpu线程中执行

 

(2) java多线程并不是由于cpu线程数为多个才称为多线程,当Java线程数大于cpu线程数,操作系统使用时间片机制采用线程调度算法,频繁的进行线程切换

 

(3) 线程是操作系统最小的调度单位,进程是资源(比如:内存)分配的最小单位

 

(4)Java中的所有线程在JVM进程中,CPU调度的是进程中的线程

****时间片机制:又称RR调度,会导致上下文切换

3. 什么是进程和线程

进程:程序运行资源分配的最小单位,进程内部有多个线程,会共享这个进程的资源
线程:CPU调度的最小单位,必须依赖进程而存在。

 

4. 澄清并行和并发

并行:同一时刻,可以同时处理事情的能力

并发:与单位时间相关,在单位时间内可以处理事情的能力

 

 

5. 高并发编程的意义、好处和注意事项

好处:充分利用cpu的资源、加快用户响应的时间,程序模块化,异步化
问题:
线程共享资源,存在冲突;
容易导致死锁;
启用太多的线程,就有搞垮机器的可能

6.查看 JVM自启动线程

public static void main(String[] args) {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
        for (ThreadInfo threadInfo : threadInfos) {
            System.out.println("[" + threadInfo.getThreadId() + "]" + " " + threadInfo.getThreadName());
        }
    }

 

Attach Listener(附加听众) :线程是负责接收到外部的命令,而对该命令进行执行的并且吧结果返回给发送者。通常我们会用一些命令去要求jvm给我们一些反馈信息,如:java -version、jmap、jstack等等。如果该线程在jvm启动的时候没有初始化,那么,则会在用户第一次执行jvm命令时,得到启动。
signal dispather(信号分配器): 前面我们提到第一个Attach Listener线程的职责是接收外部jvm命令,当命令接收成功后,会交给signal dispather线程去进行分发到各个不同的模块处理命令,并且返回处理结果。signal dispather线程也是在第一次接收外部jvm命令时,进行初始化工作。
Finalizer(终结器): 用来执行所有用户Finalizer 方法的线程

       1)只有当开始一轮垃圾收集时,才会开始调用finalize()方法;因此并不是所有对象的finalize()方法都会被执行;

  2)该线程也是daemon线程,因此如果虚拟机中没有其他非daemon线程,不管该线程有没有执行完finalize()方法,JVM也会退出;

  3) JVM在垃圾收集时会将失去引用的对象包装成Finalizer对象(Reference的实现),并放入ReferenceQueue,由Finalizer线程来处理;最后将该Finalizer对象的引用置为null,由垃圾收集器来回收;

  4) JVM为什么要单独用一个线程来执行finalize()方法呢?如果JVM的垃圾收集线程自己来做,很有可能由于在finalize()方法中误操作导致GC线程停止或不可控,这对GC线程来说是一种灾难;


Reference Handler(引用处理程序) :JVM在创建main线程后就创建Reference Handler线程,其优先级最高,为10,它主要用于处理引用对象本身(软引用、弱引用、虚引用)的垃圾回收问题。

main:这4个线程,加上,main,所以总共会有5个线程被创建,可以通过上面的这几行代码来查看:

但是,当前活动的线程只有1个,就是main,System.out.println(Thread.activeCount()); 用这条命令返回值是1。这也经常被用作以下场合的判断

比如,在main线程中创建多个子线程后,如果子线程的耗时比main线程要长,main线程就会再子线程之前结束。假如main线程的结果需要用到子线程的返回值,那么我们通常就在main线程中加上这句代码:

  System.out.println(Thread.activeCount() >1),

来判断子线程是否全部运行结束,也就是当前活动线程只有main线程一个。这样做在windows下是没错的,但是!!!

在linux下就不是这样了,你会发现,即使所有的子线程全部结束,打印当前的活动线程是2!!!而不是1,除了main线程之外,linux下还会有一个Monitor Ctrl-Break 线程存在,这个线程是用来干嘛的呢?

Monitoring Thread Activity With Thread Dumps Thread dumps, or "thread stack traces," reveal information about an application's activity that can help you diagnose problems and better optimize application and JVM performance; for example, thread dumps can show the occurrence of "deadlock" conditions, which can seriously impact application performance. You can create a thread dump by invoking a control break (usually by pressing Ctrl-Break or Ctrl-\ or SIGQUIT on linux). This section provides information on working with thread dumps. It includes information on these subjects: 1.Lock Information in Thread Dumps 2.Detecting Deadlocks

这是oracle官网的原话。大家可以自行翻译。 结论:在windows下可以用 Thread.activeCount() >1来判断子线程是否全部结束,但是linux中应该是 Thread.activeCount() > 2

    • Java management包
      management包中提供了比较全面的监控和管理工具,包括JVM的监管API、监管API日志等等。
    • 管理接口
      PlatformManagementObject接口:所有的管理接口都要继承该接口,这个接口是从1.7才出现的,从其文档的注释中可以看到其存在的价值是为以后平台的扩展而设计的,而不是为了应用程序。
      BufferPoolMXBean接口:缓冲池管理接口包括direct和mapped类型的缓冲池。
      ClassLoadingMXBean接口:类加载管理接口,可以监控管理虚拟机类加载系统。
      CompilationMXBean接口:虚拟机的编译系统的管理与监控。
      GarbageCollectorMXBean接口:虚拟机垃圾收集的管理接口,通过该接口可以查看垃圾收集的时间和次数。
      MemoryManagerMXBean接口:该接口用于内存管理,其中,垃圾收集器属于该类型的内存管理器。
      MemoryMXBean接口:用于虚拟机的内存管理,执行GC、获取堆内存和非堆内存相关数据。
      MemoryPoolMXBean接口:用于内存池的管理,所谓的内存池表示的是虚拟机使用和内存管理者管理的内存资源。
      OperatingSystemMXBean接口:操作系统管理接口,可以查看系统的平均负载、系统参数、可用的进程数、系统版本和名称等等。
      PlatformLoggingMXBean接口:日志管理接口,可以设置日志级别、获取日志名称等等。
      RuntimeMXBean接口:虚拟机运行时管理接口,获取虚拟机的名称、虚拟机版本、获取java的classpath、获取系统参数等。
      ThreadMXBean接口:虚拟机线程管理。可以获取线程数、获取线程Id、线程信息、当前线程CPU时间、当前线程用户时间、查看死锁线程等等。
    • 信息类实体
      LockInfo:任何的java锁(简单的java锁和Concurrent包中所使用的锁,AbstractOwnableSynchronizer和Condition的实现类/子类)。
      MemoryUsage:内存使用快照,用于获取每个虚拟机或者堆或者虚拟机非堆内存池作为整体的使用信息。
      MemoryNotificationInfo:内存通知的信息。
      MonitorInfo:继承自LockInfo,同步代码块或者是同步方法上的锁。
      ThreadInfo:线程信息,包括线程名称,线程id,阻塞时间,阻塞次数,等待时间,等待次数,锁信息,锁名称,锁拥有者id等。
      ManagementPermission:权限管理类。
    • 工厂类
      ManagementFactory:MXBean通过该工厂类进行获取,使用了工厂模式管理,经过该类获取到相应的MXBean类之后再调用其中的方法得到需要管理和监控的信息。

 

7.查看 JVM自启动线程

在Java的多线程编程中,java.lang.Thread类型包含了一些列的方法start(), stop(), stop(Throwable) and suspend(), destroy() and resume()。通过这些方法,我们可以对线程进行方便的操作,但是这些方法中,只有start()方法得到了保留。

在JDK帮助文档以及Sun公司的一篇文章《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 》中都讲解了舍弃这些方法的原因。
posted @ 2019-04-29 23:24  宥宥美美  阅读(369)  评论(0编辑  收藏  举报