一、进程与线程是什么?
- 进程是一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,进程也是程序的⼀次执⾏过程,是系统运⾏程序的基本单位;系统运⾏⼀个程序即是 ⼀个进程从创建、运⾏到消亡的过程。
- 线程是进程的一个执行单元,一个进程最少有一个线程,一个进程可以有多个线程,称为多线程程序
二、并行与并发
- 并行指的是在具体时刻时有两个及以上的事件发生(同时)
- 并发指的是在一段时间内有两个及的事件发生
在单核cpu计算机上,只能进行并发处理多个任务,每⼀时刻只能有⼀道程序执行,即微观上这些程序是分时的交替运行,在处理多进程时,每个线程轮流获取cpu资源,只不过是给人的感觉是同时运行,那是因为分时交替运行的时间是非常短的。
三、线程类介绍(Thread类)
线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。
每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。在java中线程的优先级默认为5(1-10内)
Thread类在java.lang包中,在java中所有的线程都是Thread类或者其子类的实例
1.Thread类的构造以及常用方法
2.创建线程类
方法1: 继承Thread类
public class MyThread extends Thread { //继承Thread类
// 构造⽅法
public MyThread(String name) {
// 调⽤⽗类的String参数的有参构造⽅法
super(name);
}
//重写run方法,run方法就是新线程的线程执行体
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName() + ":正在执⾏!" + i);
}
}
public class Demo1 {
public static void main(String[] args) {
// 创建⾃定义线程对象
MyThread newThread = new MyThread("新线程");
// 新线程执行
newThread.start();
}
}
方法2: 实现Runnable接口
public class MyFirstThread2 implements Runnable{ //实现Runnable接口
@Override //重写run方法
public void run() {
for (int i = 0; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
public class TestMyFirstThread2 {
public static void main(String[] args) {
//先创建自定义线程对象
MyFirstThread2 cs = new MyFirstThread2();
//构造方法写入新线程名字
Thread newThread = new Thread(cs, "newThread");
//运行新线程
newThread.start();
}
}
3.多线程
其实在之前创建线程类时我们在在定义的线程类中重写了run方法,并且在测试类中在main方法里执行其他的代码块就实现了多线程
虚拟机在运行时先进入main方法执行我们自己创建的新线程,会在内存中开辟一个新的空间给新线程,之后main线程继续执行
public class MyThread2 implements Runnable{
public static void main(String[] args) {
MyThread2 runnable = new MyThread2();
Thread thread = new Thread(runnable,"小徐");
System.out.println("自定义线程处于创建状态");
thread.start();
System.out.println("自定义线程处于就绪状态");
String name = Thread.currentThread().getName();
for (int i = 0; i <3; i++) {
System.out.println(name+"正在运行");
}
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name+"线程正在运行,处于运行状态");
System.out.println(name+"线程开始休眠,处于阻塞状态");
try {
Thread.sleep(5000); //休眠五秒
System.out.println(name+"线程休眠结束,阻塞状态结束,再次进入就绪状态");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
4.用两种不同方式创建的区别
结论:使用实现Runnable接口的方式可以实现资源的共享,而使用继承Thread类的方式则不行
Runnable接口同时也解决了java中单继承的局限性,使得代码可以被多个线程共享
用买票窗口的例子演示,代码如下:
1. 继承Thread
public class TicketThread extends Thread {
private int ticket = 10;
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
if (this.ticket > 0) {
System.out.println(Thread.currentThread()
.getName() + "买票--" + this.ticket--);
}
}
}
public static void main(String[] args) {
TicketThread window1 = new TicketThread();
window1.setName("一号窗口");
TicketThread window2 = new TicketThread();
window2.setName("二号窗口");
window1.start();
window2.start();
}
}
运行结果:
资源没有共享,每个窗口都卖出了十张票
2. 实现Runnable接口
public class TicketRunnable implements Runnable {
private int ticket = 10;
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
if (this.ticket > 0) {
System.out.println(Thread.currentThread().getName()
+ "买票--" + (this.ticket)--);
}
}
}
public static void main(String[] args) {
TicketRunnable window = new TicketRunnable();
Thread window1 = new Thread(window, "窗口一");
Thread window2 = new Thread(window, "窗口二");
window1.start();
window2.start();
}
}
运行结果:
资源共享,两个窗口一共只卖出了十张票