- 程序program
完成特定任务,用语言编写的一组指令的集合。 - 进程
1.进程是运行中的程序,启动一个程序,操作系统会为进程分配内存空间。
2.进程是程序的异常执行过程,进行中的程序,是动态过程,它有自己的产生、存在和消亡的过程。
1. 线程
1.线程是由进程创建的,它是进程的实体。
2.一个进程可以拥有多个线程。
3.线程也可以拥有线程。
4.线程有自己的生命周期。
1.1 单线程
同一个时刻,只允许执行一个线程。
1.2 多线程
同一个时刻,可以执行多个线程。
1.3 线程的基本使用
- 继承Thread类,重写run方法
- 实现Runnable接口,重写run方法
1.4 Thread 类
Thread的start方法开启了一个子线程:Thread0,主线程不会阻塞,会继续执行
它的底层是调用了start调用了start0方法,start0方法调用Java底层的C/C++代码,创建了新的线程
start0还会调用重写的run方法,在新的线程中运行
/*
继承Thread类,重写run方法
*/
public class Demo01{
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.start();
}
}
class Mouse extends Thread{
@Override
public void run() {
int times = 0;
while (true){
System.out.println("鼠鼠过街,吱吱~");
times++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (times==10){
break;
}
}
}
}
1.5 Runnable 接口
因为类只能单继承,有点类以及继承了其他类,无法继承Thread类,可以实现Runnable接口
Runnable接口中只有run方法,而没有start方法,所以需要通过建立Thread的对象接收类对象(Thread中有一个Runnable类型的属性,可以接收实现了Runnable接口的对象)
来调用Thread的start方法,这是一种设计模式(静态代理)。
public class Demo02 {
public static void main(String[] args) {
Dog dog = new Dog();
Thread thread = new Thread(dog);
thread.start();
}
}
class Dog implements Runnable{
@Override
public void run() {
int times = 0;
while (true){
System.out.println("大黄狗,汪汪叫");
times++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (times==10){
break;
}
}
}
}
例子
public class Demo03 {
public static void main(String[] args) {
Tiger tiger = new Tiger();
Bird bird = new Bird();
new Thread(tiger).start();
new Thread(bird).start();
}
}
class Tiger implements Runnable{
@Override
public void run() {
int times = 0;
while (true){
System.out.println("大老虎,嗷嗷叫");
times++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (times==10){
break;
}
}
}
}
class Bird implements Runnable{
@Override
public void run() {
int times = 0;
while (true){
System.out.println("小鸟,叽叽叽~");
times++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (times==5){
break;
}
}
}
}
1.6 售票问题
public class Test01 {
public static void main(String[] args) throws InterruptedException {
Ticket1 ticket1 = new Ticket1(1000);
Ticket1 ticket2 = new Ticket1(1000);
Ticket1 ticket3 = new Ticket1(1000);
new Thread(ticket1).start();
new Thread(ticket2).start();
new Thread(ticket3).start();
Thread.sleep(3*1000);
}
}
class Ticket1 implements Runnable {
private static int num = 100;
private int sleep;
public Ticket1(int sleep) {
this.sleep = sleep;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
num--;
System.out.println(Thread.currentThread().getName()+"窗口售出:"+"剩余票数:"+num);
if (num <= 0) {
System.out.println("售完");
break;
}
}
}
}
售票员可能会多卖出1-2张票,这是因为当票售完时,某个售票员已经进入了售票过程,也就是循环体中。这时就会多卖票。
这是因为Thread和Runnable是线程不安全的。
1.7 线程终止
我们可以通过在类的属性中加入一个flag,再通过对flag进行控制,来控制线程的终止。
public class Test01 {
public static void main(String[] args) throws InterruptedException {
Ticket1 ticket1 = new Ticket1(1000);
Ticket1 ticket2 = new Ticket1(1000);
Ticket1 ticket3 = new Ticket1(1000);
new Thread(ticket1).start();
new Thread(ticket2).start();
new Thread(ticket3).start();
Thread.sleep(3*1000);
ticket1.setLoop(false);
ticket2.setLoop(false);
ticket3.setLoop(false);
}
}
class Ticket1 implements Runnable {
private static int num = 100;
private int sleep;
private boolean loop = true;
public boolean isLoop() {
return loop;
}
public void setLoop(boolean loop) {
this.loop = loop;
}
public Ticket1(int sleep) {
this.sleep = sleep;
}
@Override
public void run() {
while (loop) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
num--;
System.out.println(Thread.currentThread().getName()+"窗口售出:"+"剩余票数:"+num);
if (num <= 0) {
System.out.println("售完");
break;
}
}
}
}
2. 并发和并行
2.1 并发
同一时刻,多个任务交替执行,造成一种"同时“的错觉,这是因为单核cpu的效率高。
简单说,单核cpu实现多任务就是并发。
2.2 并行
同一时刻,多个任务同时执行,多喝cpu可以实现并行。
3. 线程常用方法
1.setName //设置线程名称,使之与参数name相同
2.getName //返回该线程的名称
3.start //使该线程开始执行;Java虚拟机底层调用该线程的start()方法
4.run //调用线程对象run方法
5.setPriority //更改线程的优先级
6.getPriority //获取线程的优先级
7.sleep //在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
8.interrupt //中断线程的优先级