Java多线程理论和手把手代码教程

本文深入解析Java多线程理论,涵盖线程创建、进程与线程的区别、JVM多线程机制及其实现方式,包括继承Thread类和实现Runnable接口的方法,适合初学者快速上手。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java多线程理论和手把手代码教程

  • 定义:一个基本的概念就是同时对多个任务加以控制。许多程序设计问题都要求程序能够停下手头的工作,改为处理其他一些问题,再返回主进程。可以通过多种途径达到这个目的。
  • 多线程的作用:通俗的讲为了实现同一时间干多件事情。
  • 注意点:多个线程之间是抢CPU的关系,线程之间有随机性。

关于程序、进程、线程、任务区的理解

  • 程序:通俗的讲就是一个可执行的文件。
  • 进程:一个正在运行的程序。也可以理解成在内存中开辟了一块儿空间。
  • 线程:负责程序的运行,可以看做一条执行的通道或执行单元,所以我们通常将进程的工作理解成线程的工作。
  • 任务区:我们将线程工作的地方称为任务区。每一个线程都有一个任务区,任务区通过对应的方法产生作用。

进程和线程的关系

  • 列一个小问题给出关系:进程中可不可以没有线程?
    • 答案: 必须有线程,至少有一个.当有一个线程的时候我们称为单线程(唯一的线程就是主线程)。当有一个以上的线程同时存在的时候我们称为多线程。

关于JVM的多线程问题

  • JVM至少有两个线程:
    • 主线程:任务区是main函数。
    • 垃圾回收线程:任务区是finalize函数。
  • 关于JVM的两个线程的例子
	class Test{
		/*
		 * finalize()方法应该由系统调用,为了模拟多线程的环境,我们将它进行了重写
		 * 正常情况下,当Test类的对象被释放的时候,finalize方法会被自动调用.
		 * @see java.lang.Object#finalize()
		 */
		protected void finalize() throws Throwable {
			System.out.println("finalize()");
		}
	}
	
	public class Demo9 {
		public static void main(String[] args) {
			new Test();
			//手动执行gc方法,运行垃圾回收器,触发垃圾回收机制
			/* 原理:当执行gc的时候,会触发垃圾回收机制,开启垃圾回收线程,调用finalize()方法.
			 */
			System.gc();
			//当执行到这里的时候,正常情况下有两个线程:主线程和垃圾回收线程
			System.out.println("main");
		}//线程是随着任务的开始而开始结束而结束.只要任务没有结束,线程就不会结束.当线程还在工作的时候,进程没有办法结束.
	}

多线程编程的两种创建模式

1. 继承Thread类的方式

a. 创建Thread的子类的方式

	class MyThread extends Thread {
		/*
		 * 重写run方法---作为任务区 ,完成我们自己的功能
		 * Thread.currentThread():获取的是当前线程
		 * .getName():获取名字;
		 */
		@Override
		public void run() {
			for (int i = 0; i < 10; i++) {
				System.err.println(Thread.currentThread().getName() + ":" + i);
			}
		}
	}

	public class Demo2 {
		public static void main(String[] args) {//这儿有两个线程,一个主线程、一个垃圾回收线程。一般先暂时忽略垃圾回收线程
			Thread thread1 = new MyThread();
			Thread thread2 = new MyThread();
			thread1.start();
			thread2.start();
			
			//主线程的工作代码
			for (int i = 0; i < 10; i++) {
				System.err.println(Thread.currentThread().getName() + ":" + i);
			}
		}
	}
  • 注意点:我们如果想run作为任务区,必须通过执行start方法,让run自动执行,不能手动调用。如果手动调用run方法,他只是一个普通方法,不代表任务区,只有自动调用的时候才代表任务区。手动调用的时候在哪儿调用,run方法内部在哪儿就是哪个线程。

b.直接匿名内部用类方法

	public class Demo2 {
		public static void main(String[] args) {//这儿有两个线程,一个主线程、一个垃圾回收线程。一般先暂时忽略垃圾回收线程
			//1.通过Thread类直接创建线程
			new Thread() {
				@Override
				public void run() {
					for (int i = 0; i < 100; i++) {
						System.out.println(Thread.currentThread().getName() + ":" + i);
					}
				}
			}.start();
			new Thread() {
				@Override
				public void run() {
					for (int i = 0; i < 100; i++) {
						System.out.println(Thread.currentThread().getName() + ":" + i);
					}
				}
			}.start();
		}
	}
  • 通过匿名内部内直接new一个Thread类,然后重写run方法,最后再执行start()方法。
2. 实现Runnable接口的方法
  • 理念:实现了线程与任务分离。
  • 好处:哪个线程工作,就将哪个线程交给谁,操作方便。
  • 实现
	//创建任务类
	class Ticket implements Runnable{
		//因为Ticket对象被4个线程共享,所以num也被共享
	    int num = 40;
		public void run() {
			for(int i=0;i<10;i++){
				System.out.println(Thread.currentThread().getName()+"  i:"+i+"   "+ --num);
			}
	    }
	}
	public class Demo3{
		public static void main(String[] args) {
			//1.先创建一个任务类对象
			Ticket ticket = new Ticket();
			
			//2.创建线程并绑定任务
			Thread thread1 = new Thread(ticket);
			Thread thread2 = new Thread(ticket);
			Thread thread3 = new Thread(ticket);
			Thread thread4 = new Thread(ticket);

			//3.开启线程
			thread1.start();
			thread2.start();
			thread3.start();
			thread4.start();
		}
	}
  • 注意点: 如果我们自己创建了独立的任务类,线程会优先调用我们手动传入的任务类对象的run方法,不会再去调用Thread类默认的run方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值