一.进程和线程:
1.进程:一个程序正在内存里运行,就会有至少一个进程
2.线程:一个进程由多个线程组成。让我们举个列子:有一个洗碗的任务,在只有一个主线程的时候,那么它既要去拿碗,又要洗碗,还要放碗,所有事情都是它一个人完成。现在新加线程,将不同的任务分离开,一个人只完成一个小任务,提高效率,也进行了解耦的作用。
注:我们所常用的main方法,就是一个主线程。
二.创建一个线程(两种方式)
1.实现runable接口,重写run方法,建议用接口,下面的实列都以此为标准。
package com.swpu.run;
public class Demo01 implements Runnable{
@Override
public void run() {
for(int i=0;i<1000;i++) {
System.out.println(i);
}
}
}
2.继承Thread类,重写run方法,实质上Thread类也实现了runable接口
package com.swpu.run;
public class Demo02 extends Thread{
@Override
public void run() {
for(int i=0;i<1000;i++) {
System.out.println(i);
}
}
}
三.线程的生命周期:
1.创建一个Thread对象,该线程就进入新建状态.
创建代码:Thread t1=new Thread(new Demo01);
2.启动,进入就绪状态:t1.start();
3.线程抢占到cpu进入运行状态,一个进程有多个线程,会同时去抢占CPU。谁抢到,谁运行,1s中能抢好几百次。
4.线程人为睡眠,打断等进入阻塞状态,从阻塞状态恢复后又进入就绪状态
5.线程结束,进入死亡状态
四.线程的方法:
1.main方法中新建线程:
Thread t1=new Thread(new Demo01);
t1.start();
hihq
如图为Thread类中的方法:
1.start():启动线程,处于就绪状体
2.run():是线程中代码真正执行的地方,需重写,也就是运行状态执行的地方
3.setName(String name):每个线程都有一个属于自己的名字,可自己定义,也可默认,此为自定义
4.setPriority():设置优先级,默认为5,范围为1-10,此为自定义
5.setDaemon():设置当前线程是否为守护线程,若为true,则JVM在没有非守护线程时,可自己退出,无需等待此守护线程。
6.join():阻塞当前运行线程,直至调用该方法的线程处于死亡状态,在重新调用该线程。如:main()方法中调用t1.join();,则主线程进入阻塞状态,直至t1运行完毕,main方法重新启动。
7.interrupt():中断当前线程,进入阻塞状态
8.isAlive():判断当前线程是否处于活动状态
9.sleep():进入休眠状态,此时为阻塞状态
五.多线程的问题:
在多线程中,如果都要堆同一资源进行调用,且有序的话,就要用锁来锁住资源,否则会造成资源被多个线程”同时“消费。无法控制。
synchronized(资源名){}
锁住资源,若想按一定顺序调用,使用wait()和notify(),notifyall()三个方法调度