Java线程基础part1

本文深入解析了进程和线程的概念,阐述了它们在程序运行中的作用,包括单线程和多线程的区别,以及Java中创建和管理线程的具体方法。

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

进程和线程

  • 进程:正在运行的程序。当一个程序进入内存运行就变成一个进程,进程是处于运行过程中的程序,具有一定独立功能。

  • 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
    一个程序运行后至少有一个进程,一个进程可以包含多个线程。

  • 多线程:一个程序中有多个线程同时执行。

    • 单线程程序:多个任务只能依次执行。
    • 多线程程序:多个任务可以同时执行。
  • 分时调度:所有线程轮流使用CPU,平均分配每个线程使用CPU的时间。

  • 抢占式调度:优先让优先级高的线程使用CPU,如果优先级相同,那么随机选择一个线程执行,Java使用的是抢占式调度。

抢占式调度中,CPU在每个线程之间高速切换。这种方式可以提高CPU的使用率,提高程序的运行效率(但不能提高程序的运行速度)。

主线程

在单线程的java程序中,通过main方法开始执行代码,以下面代码为例:

public class Demo {
	public static void main(String[] args) {
		function();
		System.out.println(Math.abs(-9));
	}
	
	public static void function() {
		for(int i = 0; i < 10000; i++) {
			System.out.println(i);
		}
	}
}

在function()函数中的循环执行完成之前,System.out.println(Math.abs(-9));代码是不会执行的。原因是:jvm启动后,必然有一个执行路径(线程)从main方法开始的,一直执行到main方法结束,这个线程在java中称之为主线程。当程序的主线程执行时,如果遇到了循环而导致程序在指定位置停留时间过长,则无法马上执行下面的程序,需要等待循环结束后能够执行。
如果可以创建一个线程,让主线程执行循环,另一个线程执行打印操作,就实现了前面提到的多线程。

Thread类

在java中创建线程的一种方式是继承Thread类。步骤为:
1.定义一个类继承Thread类。
2.重写run()方法。(run()方法不能抛出异常)
3.创建子类对象,即创建线程对象。
4.调用start()方法,让线程开始执行。同时告诉JVM调用run()方法

/*
 * 定义子类继承Thread
 * 重写父类的方法run
 */
public class SubThread extends Thread{
	public void run() {
		for(int i = 0; i < 50; i++) {
			System.out.println("run..." + i );
		}
	}
}
/*
 * 创建和启动一个线程
 * 	创建Thread子类对象
 * 	子类对象调用方法start()
 * 		start():让线程程序执行,JVM调用子类中的run
 */
public class ThreadDemo {
	public static void main(String[] args) {
		SubThread st = new SubThread();
		SubThread st1 = new SubThread();
		st.start();
		st1.start();
		for(int i = 0; i < 50; i++) {
			System.out.println("main..." + i );
		}
	}
}

多线程的运行结果:

可以看到几个线程交替运行。

线程的名字

每个线程都有自己的名字,运行方法main线程名字就是“main”。 其他新建的线程也有自己的名字,默认"Thread-0","Thread-1"。如果想要获取线程名字,可以使用父类Thread的方法getName()。另外 Thread类中定义了静态方法 static Thread currentThread()返回正在执行的线程对象。
创建线程对象后调用父类Thread方法setName(String name)可以给线程命名,但一般不这么做。
JVM开启主线程,运行方法main,主线程也是线程,是线程必然就是Thread对象。

线程休眠

Thread的静态方法sleep(int time),可以让线程休眠指定毫秒值。(会抛出异常)

public class SleepThread extends Thread{
	public void run() {
		for(int i = 0; i < 5; i++) {
			try {
				Thread.sleep(1000);				
			}catch(Exception ex) {
				System.out.println(ex);;
			}
			System.out.println(i);
		}
	}
}

public class ThreadDemo {
	public static void main(String[] args) throws InterruptedException {
		SleepThread st = new SleepThread();
		st.start();
	}
}

Runnable接口

实现线程的另一种方式:实现Runnable接口,重写run()方法

public class SubRunnable implements Runnable{
	public void run() {
		for(int i = 0; i < 50; i++) {
			System.out.println("run..." + i);
		}
	}
}

public class ThreadDemo {
	public static void main(String[] args) {
		SubRunnable sr = new SubRunnable();
		Thread t = new Thread(sr);
		t.start();
		for(int i = 0; i < 50; i++) {
			System.out.println("main..." + i);
		}
	}
}

实现Runnable接口避免了继承Thread类的单继承局限性。实现Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。继承Thread类,线程对象和线程任务耦合在一起。一旦创建Thread类的子类对象,既是线程对象,有又有线程任务。实现runnable接口,将线程任务单独分离出来封装成对象,类型就是Runnable接口类型。Runnable接口对线程对象和线程任务进行解耦。

使用匿名内部类创建线程

代码

/*
 * 使用匿名内部类,实现多线程程序
 * 前提:继承或接口实现
 * new 父类或者接口()
 * 		重写抽象方法
 */
public class ThreadDemo {
	public static void main(String[] args) {
		//继承方式 XXX extends Thread{public void run(){}}
		new Thread() {
			public void run() {
				System.out.println("!!!");
			}
		}.start();
		
		//实现接口方式 XXX implements Runnable{public void run(){}}
		Runnable r = new Runnable() {
			public void run() {
				System.out.println("###");
			}
		};
		new Thread(r).start();
		
		new Thread(new Runnable() {
			public void run() {
				System.out.println("@@@");
			}
		}).start();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值