进程是程序的一次动态执行过程,是程序代码加载 -> 代码执行 -> 执行完成的过程,此过程也是进程本身从产生,发展到最终消亡的过程。目前我们的操作系统均是多进程操作系统,能同时运行多个进程(程序),由于 CPU 具备分时机制,所以每个进程都能循环获得自己的 CPU 时间片,而且 CPU 执行速度非常快,使得所有程序好像是在同时运行一样。
多线程是实现并发机制的一种有效手段。进程和线程一样,都是实现并发的基本单位。线程是比进程更小的执行单位,是在进程的基础上更进一步的划分。所谓多线程是指一个进程在执行过程中产生的多个更小的程序单元,这些更小的单元称为线程,这些线程可以同时存在,同时运行,一个进程可能包含多个同时执行的线程。
Java程序每次运行时,至少启动两个线程,一个是mian线程,另一个是垃圾收集线程(Java本身具备垃圾回收的机制)。
Java可通过继承 Thread 类或实现 Runnable 接口来实现多线程。本文以集成 Thread 类为例实现多线程。代码如下所示:
package com.fanfengping.demo; import lombok.extern.slf4j.Slf4j; /** * Java程序里面对于继承永远都是存在有单继承局限的 */ @Slf4j public class ThreadDemo extends Thread{ private Thread t; // 线程名称 private String threadName; ThreadDemo(String tName) { threadName = tName; log.info("Create a thread : {}", threadName); } // 重写 run 方法,作为线程操作主体 public void run() { log.info("Running Runnable Thread : {}", threadName); try { for(int i = 3; i > 0; i--) { log.info("Current Thread name is {}, work batch : {}", threadName, i); Thread.sleep(500); } } catch (InterruptedException e) { log.info("Thread {} interrupted!", threadName); e.printStackTrace(); } log.info("Thread {} exit", threadName); } public void start() { log.info("Start Thread : {}", threadName); if (t == null) { t = new Thread(this, threadName); t.start(); } } }
编写测试类,代码如下所示:
package com.fanfengping.demo; public class ThreadDemoTest { public static void main(String args[]) { ThreadDemo t1 = new ThreadDemo("ThreadDemo-1"); t1.start(); ThreadDemo t2 = new ThreadDemo("ThreadDemo-2"); t2.start(); ThreadDemo t3 = new ThreadDemo("ThreadDemo-3"); t3.start(); ThreadDemo t4 = new ThreadDemo("ThreadDemo-4"); t4.start(); ThreadDemo t5 = new ThreadDemo("ThreadDemo-5"); t5.start(); } }
控制台输出如下所示:
[main] INFO com.fanfengping.demo.ThreadDemo - Create a thread : ThreadDemo-1 [main] INFO com.fanfengping.demo.ThreadDemo - Start Thread : ThreadDemo-1 [main] INFO com.fanfengping.demo.ThreadDemo - Create a thread : ThreadDemo-2 [main] INFO com.fanfengping.demo.ThreadDemo - Start Thread : ThreadDemo-2 [ThreadDemo-1] INFO com.fanfengping.demo.ThreadDemo - Running Runnable Thread : ThreadDemo-1 [main] INFO com.fanfengping.demo.ThreadDemo - Create a thread : ThreadDemo-3 [main] INFO com.fanfengping.demo.ThreadDemo - Start Thread : ThreadDemo-3 [ThreadDemo-1] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-1, work batch : 3 [ThreadDemo-2] INFO com.fanfengping.demo.ThreadDemo - Running Runnable Thread : ThreadDemo-2 [ThreadDemo-2] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-2, work batch : 3 [main] INFO com.fanfengping.demo.ThreadDemo - Create a thread : ThreadDemo-4 [main] INFO com.fanfengping.demo.ThreadDemo - Start Thread : ThreadDemo-4 [ThreadDemo-3] INFO com.fanfengping.demo.ThreadDemo - Running Runnable Thread : ThreadDemo-3 [main] INFO com.fanfengping.demo.ThreadDemo - Create a thread : ThreadDemo-5 [ThreadDemo-3] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-3, work batch : 3 [main] INFO com.fanfengping.demo.ThreadDemo - Start Thread : ThreadDemo-5 [ThreadDemo-4] INFO com.fanfengping.demo.ThreadDemo - Running Runnable Thread : ThreadDemo-4 [ThreadDemo-4] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-4, work batch : 3 [ThreadDemo-5] INFO com.fanfengping.demo.ThreadDemo - Running Runnable Thread : ThreadDemo-5 [ThreadDemo-5] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-5, work batch : 3 [ThreadDemo-1] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-1, work batch : 2 [ThreadDemo-4] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-4, work batch : 2 [ThreadDemo-3] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-3, work batch : 2 [ThreadDemo-2] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-2, work batch : 2 [ThreadDemo-5] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-5, work batch : 2 [ThreadDemo-1] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-1, work batch : 1 [ThreadDemo-3] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-3, work batch : 1 [ThreadDemo-4] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-4, work batch : 1 [ThreadDemo-5] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-5, work batch : 1 [ThreadDemo-2] INFO com.fanfengping.demo.ThreadDemo - Current Thread name is ThreadDemo-2, work batch : 1 [ThreadDemo-4] INFO com.fanfengping.demo.ThreadDemo - Thread ThreadDemo-4 exit [ThreadDemo-1] INFO com.fanfengping.demo.ThreadDemo - Thread ThreadDemo-1 exit [ThreadDemo-5] INFO com.fanfengping.demo.ThreadDemo - Thread ThreadDemo-5 exit [ThreadDemo-2] INFO com.fanfengping.demo.ThreadDemo - Thread ThreadDemo-2 exit [ThreadDemo-3] INFO com.fanfengping.demo.ThreadDemo - Thread ThreadDemo-3 exit
从上述程序运行输出日志可以看出,多个线程对象是交错运行的。线程是否运行,取决于线程对象是否被分配并获得了 CPU 资源。所以程序每次的运行结果通常是不一样的。另外,线程启动时虽然调用的是 start() 方法,实际上最终调用的却是 run() 方法定义的主体。
线程命名方式有如下两种:
- 系统默认生成:new Thread(ThreadDemo)
- 指定线程名称:new Thread(ThreadDemo, "线程名称")