线程和进程联系以及线程的创建

本文深入探讨了进程与线程的概念,强调了它们在资源分配和执行上的区别。进程作为操作系统分配资源的基本单位,而线程则是处理器调度的基本单位,拥有更低的开销。Java中的JVM进程包含多个线程,如垃圾收集线程等。文章还详细介绍了Java中四种线程的创建方式:继承Thread、实现Runnable接口、实现Callable接口以及使用线程池,并给出了示例代码。最后,提到了线程命名的方法。
摘要由CSDN通过智能技术生成

目录

一、浅谈进程

二、JVM进程

三、线程的创建方式

3.1 通过继承Thread创建线程

3.2 实现Runnable 接口(线程执行类)

3.3实现  Callable 接口,允许子线程返回结果、抛出异常

3.4线程池

四、线程的命名


一、浅谈进程

进程:是操作系统资源分配的基本单位。它是程序的一次执行,是系统运行程序的基本单位。

一个进程包含多个线程,至少包含一个主线程。

问题1:那么什么是线程呢?

线程是比进程更小的执行单位(CPU最小的执行单位)

问题2:线程和与进程的区别(重点)

(1) 根本区别 :进程是操作系统分配内存资源的基本单位,线程是处理器任务调度和执行的基本单位

(2)资源开销: 每个进程都有独立的代码副本和数据空间,进程之间的切换,资源开销较大。线程可以看做是轻量级的进程,每个线程都有自己的独立的运行栈和程序计数器,线程之间的切换,资源开销较小。

(3)包含关系:一个进程包含多个线程的,在执行过程中,线程的执行不是线性串行的,它是并行同步进行的

(4)内存分配:一个进程中的多个线程共享本进程的内存空间和资源,进程之间的内存空间和资源相互独立

(5) 影响关系:一个进程崩溃后,在保护模式下,不会对其他线程造成影响,一个线程崩溃后,会对本进程造成影响,使其退出。故多线程比多线程健壮。

(6)执行过程:每个进程都有程序入口和程序出口,但是线程不能独立执行,必须依靠在应用程序(进程中),由应用程序提供多个线程执行控制。

二、JVM进程

进程启动后,jvm内存区域分配,各线程共享元空间区,堆区资源

每个线程都有自己的本地方法栈,程序计数器,虚拟机栈,线程是轻量级进程,资源开销小

JVM进程都包含哪些线程呢? 

public static void main(String[] args) {
		// 获取 Java 线程管理对象 ThreadMXBean
		ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

		// 不需要获取的锁监视器 lockedMonitor 和 synchronizer 信息
		// 仅获取线程和线程信息
		ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);

		// 遍历线程信息,仅打印线程 ID 和线程名称信息
		for (ThreadInfo threadInfo : threadInfos) {
			System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.getThreadName());
		}
	}

执行结果

[5] Attach Listener 添加时间监听器
[4] Signal Dispatcher 分发处理给 JVM 信号的线程
[3] Finalizer 调用对象 finalize 方法的线程(重写object类)
[2] Reference Handler  清除 reference 线程
[1] main   主线程

那么有人会问了,如果是多线程呢,主线程和子线程都存在,会先执行哪一个呢?

答:main主线程与子线程同时运行,由操作系统调度,程序本身无法确定线程的调度顺序

三、线程的创建方式

3.1 通过继承Thread创建线程

//线程的子类
class Test extends Thread {

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName() + ":" + i);
		}
	}
}

public class Demo03 {
	public static void main(String[] args) {

		Test t1 = new Test();
		Test t2 = new Test();
		Test t3 = new Test();
		//启动线程
		t1.start();
		t2.start();
		t3.start();
	}
}

3.2 实现Runnable 接口(线程执行类)

class task implements Runnable {

	@Override
	public void run() {
		for (char i = 'a'; i <= 'z'; i++) {
			System.out.println(Thread.currentThread().getName() + ":" + i);
		}
	}

}
//实现Runnable 接口(线程执行类)
public class Demo04 {
	public static void main(String[] args) {

		// 创建3个线程执行逻辑
		task t2 = new task();
		task t1 = new task();
		task t3 = new task();

		// 调用了一个普通的Java方法,当前线程并没有任何改变,也不会启动新线程。
//		t1.run();
//		t2.run();
//		t3.run();

		Thread thread = new Thread(t1);
		Thread thread1 = new Thread(t2);
		Thread thread2 = new Thread(t3);
		thread.start();
		thread1.start();
		thread2.start();

		// 主线程继续同时向下执行
		for (int i = 0; i < 100; i++) {
			System.out.println("主线程" + i + " ");
		}

		System.out.println("主线程执行完毕了");
	}
}

3.3实现  Callable 接口,允许子线程返回结果、抛出异常

//Runable:不会产生运行结果
//Callable:会产生运行结果
class task01 implements Callable<Integer> {

	private int begin;
	private int end;

	public task01(int begin, int end) {
		this.begin = begin;
		this.end = end;
	}

	@Override
	public Integer call() throws Exception {
		int total = 0;
		for (int i = begin; i <= end; i++) {
			total += i;
		}

		return total;
	}

}
//方式三::实现  Callable 接口,允许子线程返回结果、抛出异常
public class Demo06 {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		task01 t1 = new task01(0, 5);
		task01 t2 = new task01(6, 10);

		// 创建FunturnTask对象,封装Callable接口实现类对象(线程执行逻辑)
		FutureTask<Integer> f1 = new FutureTask<Integer>(t1);
		FutureTask<Integer> f2 = new FutureTask<Integer>(t2);

		// 分别启动两个子线程
		new Thread(f1).start();
		new Thread(f2).start();

		// 分别获取两个子线程的计算结果
		int a1 = f1.get();
		int b1 = f2.get();
		System.out.println(a1 + b1);

	}
}

3.4线程池

       线程池,按照配置参数(核心线程数、最大线程数,存活时间,拒绝策略,工作队列)创建并管理若干线程对象。程序中如果需要使用线程,将一个执行任务传给线程池,线程池就会使用一个空闲状态的线程来执行这个任务。执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。使用线程池可以很好地提高性能。

public class Demo07 {
	public static void main(String[] args) {
		// 创建线程池 包含10个线程
		// pool-1-thread-1:0 线程池编号-分配线程编号
		ExecutorService executorService = Executors.newFixedThreadPool(10);


		while (true) {
			executorService.execute(new Runnable() {
				@Override
				public void run() {
					System.out.println("当前线程:" + Thread.currentThread().getName());
					try {
						// 让当前线程休眠2秒,继续执行当前线程
						Thread.sleep(2000);
					} catch (InterruptedException e) {

						e.printStackTrace();
					}

				}

			});
		}
	}
}

四、线程的命名

调用父类的setName()方法或在构造方法中给线程名字赋值;
如果没有为线程命名,系统会默认指定线程名,命名规则是Thread-N的形式

//为线程命名
public class Demo08 {
	public static void main(String[] args) {

		// 利用构造方法命名
		new Thread(new Task04(), "线程1").start();
		new Thread(new Task04(), "线程2").start();

		Thread t2 = new Thread(new Task04());
		// 利用setName("")
		t2.setName("线程3");
		t2.start();

	}
}

class Task04 implements Runnable {

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName() + ":" + i);
		}
	}

}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值