进程与线程
- 进程是程序的一次动态执行过程,对应了从代码加载,执行至执行完毕一个完整过程,也是进程本身从产生,发展至消亡的过程。
- 线程是比进程更小的执行单位。一个进程在执行过程中可以产生多个线程。多线程是指一个程序中同时存在几个执行体
线程生命周期
新建的线程在其生命周期要经历4种状态。
- 新建
一个Thread
类或其子类的对象被声明并且创建时,线程对象已经处在了新建状态,此时它已经有了相应的内存空间和其他资源。 - 运行
当线程创建后就具备了运行条件,当轮到它享用CPU资源时,即JVM将CPU使用权切换给此个线程时,此线程则就开始独自运行。
线程创建后,线程只是拥有了相应的内存资源,但是在JVM线程管理中并没有这个线程,只有当调用了start()
这个方法后,才会使此线程进入排队使用CPU资源状态。
当JVM将CPU使用权交给此线程时,如果此线程是Thread
子类创建,则立刻开始运行run
方法,所以要在子类中重写run()
方法,父类的run()
是一个空方法。 - 中断
所谓中断即在执行过程中临时停止执行。4种原因的中断。
- JVM将CPU资源从当前进程切换到其他进程。
- 线程在执行过程中,执行了
sleep(int millsecond)
方法。在经过参数millsecond
后主动排队等待CPU资源 - 执行了
wait()
方法,进入等待状态,但是不会主动进入排序。必须由其他线程调用notify()
通知他。 - 线程在使用CPU资源时,在某个操作进入了阻塞状态,必须等阻塞消失该线程才会排队使用CPU资源。
- 死亡
线程不具备继续运行的能力。
run()
方法运行完成。run()
方法被终止。
创建多线程
创建多线程有两种方法,
- 集成
Thread
类 - 实现
Runnable
接口
继承Thread
类
只需要重写run()
方法规定具体操作即可
写写代码更好记忆与理解
模拟两只蚂蚁共享主线程提供的蛋糕,两只蚂蚁轮流吃蛋糕,在吃光时进入死亡状态。一只蚂蚁在吃蛋糕时主动sleep(1000)
,不被强制中断吃蛋糕。
Cake.java
public class Cake {
private int size;
public void setSize(int size) {
this.size = size;
}
public int getSize() {
return size;
}
public void lost(int m) {
if (size-m>=0) {
size = size-m;
}
}
}
Ant.java
public class Ant extends Thread {
Cake cake;
Ant(String name, Cake c) {
cake = c;
setName(name);
}
public void run() {
while (true) {
int n = 2;
System.out.println(getName()+"吃"+n+"克蛋糕");
cake.lost(n);
try{
sleep(1000);
} catch (Exception e) {
}
System.out.println(getName()+"发现蛋糕还剩"+cake.getSize()+"克");
if (cake.getSize()<=0) {
break;
}
}
return;
}
}
Example.java
public class Exampel {
public static void main(String[] args) {
Cake cake = new Cake();
cake.setSize(10);
Ant antone = new Ant("红蚂蚁",cake);
Ant anttwo = new Ant("黑蚂蚁",cake);
antone.start();
anttwo.start();
}
}
实现Runnable
接口
实现Runnable
接口,使用Thread
类直接创建线程对象。
Thread(Runnable target)
House.java
public class House implements Runnable {
int cake;
public void setCake(int cake) {
this.cake = cake;
}
@Override
public void run() {
while (true) {
if (cake<=0) {
break;
}
int n = 2;
System.out.println(Thread.currentThread().getName()+"吃"+n+"克蛋糕");
if (cake-n>=0) {
cake = cake-n;
}
try{
Thread.sleep(1000);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName()+"发现蛋糕还剩"+cake+"克");
}
return;
}
}
Example.java
public class Example {
public static void main(String[] args) {
House house = new House();
house.setCake(10);
Thread antone = new Thread(house);
Thread anttwo = new Thread(house);
antone.setName("红蚂蚁");
anttwo.setName("黑蚂蚁");
antone.start();
anttwo.start();
}
}
线程同步
当一个线程使用某个方法时,其他线程必须等待,直到该线程使用完毕。
在设计程序时,若干线程使用同一个方法,而且希望一个线程完成后其他线程才能操作,即用synchronized
修饰方法即可。