Java多线程简介和简单使用

1. 线程简介

1.1. 线程概念

一个线程就是一个“执行流”。
每个线程之间都可以按照顺序执行自己的代码,彼此之间相对独立,同时每个线程都会执行多份代码。

1.2. 进程概念

进程是指运行起来的程序,程序运行起来需要被加载到内存中。

1.3. 线程作用

  1. 最早的CPU是单核的,但随着CPU的发展,CPU也遇到了瓶颈,于是为了进一步提高算力,便发展出了多核的CPU,而并发编程则可以更加充分的利用这一特性来充分利用CPU的资源。
  2. 有一些的任务是需要“等待IO”数据的,但在等待的这个过程中CPU是空闲的,为了提高效率,于是可以用到并发编程。

1.4. 进程和线程的联系

  1. 进程和线程是1:m的关系:一个线程一定属于一个进程,但一个进程可能有多个线程。一个进程内至少有一个线程,这一开始就有的线程被称为主线程。
  2. 创建线程比创建进程更快,销毁线程比销毁进程更快,调度线程比调度进程更快。
  3. 进程是操作系统资源分配的基本单位,线程是操作系统进行调度的基本单位。
  4. 线程间是相互独立的(隔离性),但进程间是要相互通信的。
  5. 进程和进程之间不共享内存空间,但一个进程的线程之间是共享一个内存空间的。

2. 线程执行

2.1. 示例

import java.util.Random;
public class ThreadDemo {
	private static class MyThread extends Thread {
		@Override
		public void run() {
			Random random = new Random(); while (true) {
				// 打印线程名称
				System.out.println(Thread.currentThread().getName());
				try {
					// 随机停止运行 0-9 秒
					Thread.sleep(random.nextInt(10));
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void main(String[] args) {
		MyThread t1 = new MyThread();
		MyThread t2 = new MyThread();
		MyThread t3 = new MyThread();
		t1.start();
		t2.start();
		t3.start();
		Random random = new Random();
		while (true) {
			// 打印线程名称
			System.out.println(Thread.currentThread().getName());
			try {
				Thread.sleep(random.nextInt(10));
			} catch (InterruptedException e) {
				// 随机停止运行 0-9 秒
				e.printStackTrace();
			}
		}
	}
}

//结果
Thread-0
Thread-0
Thread-2
Thread-1
Thread-2
Thread-1
Thread-0
Thread-2
main
main
Thread-2
Thread-1
Thread-0
Thread-1
main
Thread-2
Thread-2
......

2.2. 解释

在上述的代码和结果中,可以看出:

  1. 在多个线程中,每个线程间的执行顺序是随机的,和线程的启动顺序无关。
  2. 每个线程都有自己独立的调用栈。

2.3. 线程在内存中的分配

  1. PC(保存PC的值)、栈(虚拟机栈、本地方法栈)是每个线程独一份的。
  2. 因为每个线程都是独立的执行流,吓一跳要执行的指令和其他线程无关,所以又自己的PC值。
  3. 因为每个线程都是独立的执行流,有各自调用的方法链,有各自要处理的临时数据,所以栈也是独一份的。
  4. 局部变量保存在栈帧中,也就是保存在栈中,所以是线程私有的,表现为A创建的局部变量,只有A可以 使用。
  5. 类对象(Class对象)、静态属性保存在方法区中,所以是线程之间共享的,前提是有访问权限。
  6. 对象(对象内部的属性)保存在堆中,所以是线程之间共享的,前提是线程持有该对象的应用。

2.4. 创建线程

创建线程有两种办法:继承Thread类、实现Runnable接口。

2.4.1. 继承Thread类

  1. 继承Thread来创建一个线程类。
class MyThread extends Thread {
	@Override
	public void run() {
		System.out.println("这里是线程运行的代码");
	}
}
  1. 创建MyThread类的实例。
MyThread t = new MyThread();
  1. 条用start方法来启动线程。
t.start(); // 线程开始运行

2.4.2. 实现Runnable接口

  1. 实现Runnable接口
class MyRunnable implements Runnable {
	@Override
	public void run() {
		System.out.println("这里是线程运行的代码");
	}
}
  1. 创建Thread类实例,调用Thread的构造方法时将Runnable对象作为target参数。
Thread t = new Thread(new MyRunnable());
  1. 调用start方法。
t.start(); // 线程开始运行

2.4.3. 对比

  • 继承Thread类,直接调用this就代表了当前线程对象的引用。
  • 实现Runnable接口,this表示的是MyRunnable的引用,而正确的调用应该使用Thread。currentThread()。

3. 前台线程和后台线程

  1. 前台线程一般用于做交互。
  2. 后台线程(也被称为精灵线程)一般做支撑工作的线程。
  3. 我们创建的线程一般都默认为前台线程。
  4. 当前台线程退出时,后台线程也退出了。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值