并发编程(一)java运行总共有几条线程?

(一)java启动后拥有的线程

我们首先看代码,打印普通main方法执行时,程序到底有几条线程,线程又是怎样的。

public class ThreadPrint {
    public static void main(String[] args) throws JsonProcessingException, InterruptedException {
        // 获取Java线程管理MXBean
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        // 不需要获取同步的monitor和synchronizer信息,仅获取线程和线程堆栈信息
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
        // 遍历线程信息,仅打印线程ID和线程名称信息
        for (ThreadInfo threadInfo : threadInfos) {
            System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.
                    getThreadName());
        }
        Thread.sleep(1000000);
    }
}

输出结果如下:

 

下面分别介绍一下正在运行的线程:

  • [6] Monitor Ctrl-Break

      跟JVM 关系不大,他是 IDEA 通过反射的方式,开启一个随着我们运行的jvm进程开启与关闭的一个监听线程。
    复制代码
  • [5] Attach Listener

      附加侦听器,简单来说,他是 jdk 里边一个工具类提供的jvm进程之间通信的工具。
      举例来说,比如在cmd中输入 java -version,jvm中jstat、jstack、jmap、dump等。
    复制代码

    如果自己电脑没有打印这一行,可以尝试开启我们这个线程的两个方式:

    1. 通过 vm,参数开启。-XX: StartAttachListener
    2. 2.延迟开启: md --java -version --> JVM 实时开启Attach Listener线程
  • [4] Signal Dispatcher

      信号分发器。我们通过 cmd 发送jstack,传到了 jvm 进程,这时候信号分发器就要发挥作用了。
    复制代码
  • [3] Finalizer

      JVM 垃圾回收相关的内容。此处只做简单的介绍。 
      1. 只有当开始一轮垃圾收集的时候,才会开始调用finalize方法。 
      2. daemon prio=10 高优先级的守护线程。   
      3. jvm在垃圾收集的时候,会将失去引用的对象封装到我们的 Fianlizer 对象(Reference), 放入我们的 F-queue 队列中。由 Finalizer 线程执行inalize方法
    复制代码
  • [2] Reference Handler

      引用处理的线程。强,软,弱,虚。 -GC 有不同表现 - JVM深入分析
    复制代码
  • [1] main

      就是我们运行的main线程
    复制代码

(二)查看线程级别

1.可以在idea工具Terminal中输入jps查看进程的pid,我们可以看到ThreadPrint的pid是37720

2.再通过jstack pid命令可以查看到进程日志

 

 ​​​​​​​

 

其中我们把需要了解的部分拿出来 daemon表示守护线程 prio表示jvm中的优先级 os_prio表示线程在操作系统中所占的优先级

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x0000000018e04800 nid=0xc918 runnable [0x000000001967f000]
Monitor Ctrl-Break是在idea中特有的线程

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x00000000171eb000 nid=0x9230 waiting on condition [0x0000000000000000]
    prio=5 延迟开启的问题

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x00000000171d3800 nid=0x9054 runnable [0x0000000000000000]


"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00000000171c6800 nid=0xc26c in Object.wait() [0x0000000018b1e000]
(Finalizer 专注垃圾收集,垃圾收集 -- 并行收集,不阻碍用户线程,低优先级线程。 prio=8 他是一个守护线程啊。而且这个线程目前并没有真正的开启,不足以发生minorgc或者是 full gc)


"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001575f000 nid=0x9a38 in Object.wait() [0x0000000018a1f000]
(引用处理线程-GC相关线程:GC 很重要,优先级高)


"main" #1 prio=5 os_prio=0 tid=0x0000000003624000 nid=0xaba0 waiting on condition [0x000000000351f000]
(操作系统面向的是JVM 进程,JVM 进程里面向的是 我们的main函数,。所以对于我们的操作系统如何看待我们的main函数优先级,都无关紧要。 只要os 给我们jvm进程足够公平的优先级就行。)
复制代码

(三)总结

在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。处理器在这些线程上高速切换,让使用者感觉到这些线程在同时执行。

当前的main函数就是一个 JVM 进程。 打印出来的6条线程信息就是进程中的多条线程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当然可以!以下是一个简单的Java线程博文: Java线程指的是在Java程序中创建并同时运行多个线程的过程。它可以提高程序的性能和响应性,因为它允许程序在执行某些操作时同时执行其他操作。 Java提供了两种创建线程的方式:继承Thread类和实现Runnable接口。在本文中,我们将使用实现Runnable接口的方式来创建线程。 要创建一个新的线程,我们需要首先创建一个实现了Runnable接口的类。然后,我们需要在这个类中实现run()方法,这个方法将在线程开始时被调用。 接下来,我们需要创建一个Thread对象,并将实现了Runnable接口的类的实例作为参数传递给Thread对象的构造函数。最后,我们可以调用Thread对象的start()方法来启动新线程。 以下是一个简单的Java线程的例子: ```java public class MyRunnable implements Runnable { public void run() { System.out.println("MyRunnable running"); } public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); System.out.println("Main thread running"); } } ``` 在这个例子中,我们创建了一个实现了Runnable接口的类MyRunnable,并在其中实现了run()方法。然后,我们创建了一个Thread对象,并将MyRunnable类的实例传递给Thread对象的构造函数。最后,我们调用Thread对象的start()方法来启动新线程。在main()方法中,我们还打印了一条消息来表示主线程正在运行。 当你运行这个程序时,你会看到类似于以下的输出: ``` Main thread running MyRunnable running ``` 这表明主线程和新线程都在同时运行,因为我们使用了Java线程。 这只是Java线程的基础,Java还提供了许多其他的多线程特性,例如线程同步、线程池等等。希望这篇博文能够为你提供一个好的起点来学习Java线程! ### 回答2: 当下,计算机领域近年来最具热度和应用广泛的概念之一便是多线程编程。多线程编程是指在一个程序中同时执行多个线程,每个线程都是独立运行的子任务,可以减少程序执行时间和提高资源利用率。而在Java中,多线程编程则能够通过Thread类和Runnable接口来实现,使用起来也相对简单。 Java线程编程以Thread类为基础,通过继承Thread类并重写run()方法来实现多线程。在run()方法内,我们编写具体的并发执行逻辑代码。通过调用Thread类的start()方法,系统会自动创建一个线程,并调用线程的run()方法。当线程对象调用start()方法后,线程的生命周期开始,并引发线程调度器将其放入可运行线程池中。 除了通过继承Thread类实现多线程外,Java还提供了一种更灵活的方式,即实现Runnable接口。这种方式更推荐,因为Java只支持单继承,而实现接口可以解决这个问题。实现Runnable接口后,需要创建一个Thread对象,将实现Runnable接口的类实例作为参数传入Thread的构造方法。然后,通过调用Thread的start()方法,即可开启一个线程,并执行实现Runnable接口的类中的run()方法。 在进行多线程编程时,需要注意线程的同步和互斥问题。多个线程访问共享数据时,可能会出现竞态条件,导致结果出错。为了解决这个问题,Java提供了synchronized关键字来实现线程的同步。通过在关键代码块或方法前加上synchronized关键字,可以使得同一时间只有一个线程能够进入该代码区域,从而避免出现数据竞争的问题。 总结来说,Java的多线程编程为程序员提供了一种并发执行的能力,可以提高程序的性能和效率。但需要注意线程同步和互斥的问题,以保证线程之间的协同工作和正确性。掌握好多线程编程的相关知识和技巧,将能让开发者编写出更加高效和稳定的Java程序。 ### 回答3: Java线程是指在一个程序中同时运行多个线程,每个线程执行自己的任务。多线程可以提高程序的并发性和效率,使得程序能够更好地利用计算机的资源。 在Java中,可以通过继承Thread类或实现Runnable接口来创建线程。使用继承Thread类的方法,需要重写run方法,并在run方法中编写线程的逻辑。使用实现Runnable接口的方法,则需要实现run方法,并将其作为参数传递给Thread类的构造方法。 多线程的优势主要体现在以下几个方面: 1. 提高程序的响应性:当一个线程被阻塞时,其他线程可以继续工作,使得程序在处理耗时操作时能够保持响应。 2. 提高系统资源的利用率:多线程可以有效利用计算机的多核处理器,提高程序的执行效率和性能。 3. 实现复杂的并发控制:通过线程的同步与互斥,可以实现多个线程之间的协同工作,例如生产者-消费者模型、读者-写者模型等。 在编写多线程程序时,需要注意以下几点: 1. 线程安全性:多线程操作共享的数据时,需考虑线程安全,避免出现数据竞争、不一致等问题。可以使用synchronized关键字实现线程的同步和互斥。 2. 死锁问题:当多个线程相互等待对方释放资源时,可能会导致死锁。为了避免死锁,需要合理设计线程的资源申请和释放顺序。 3. 线程间的通信:多个线程之间的通信可以使用wait、notify和notifyAll等方法来实现。 总之,Java线程是一种能够充分利用计算机多核处理器的编程模型,能够提高程序的并发性和系统资源的利用率。在多线程编程时,我们需要注意线程的安全性、死锁问题和线程间的通信,以保证程序的正确性和性能。同时,也要根据具体问题的需求,选择合适的多线程编程方式,以达到最佳的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值