程序program:为完成某个特定任务,用某种语言编写的一组指令的集合。即代码
进程:运行的应用程序。当我们启动一个程序是,就相当于启动了一个进程,操作系统为其分配空间。
进程:是程序的一次执行过程,或者正在运行的程序。
进程是动态的过程,有自身产生、存在和消亡的过程。
线程:由进程创建,是进程的一个实体。一个进程可以存在多个线程。
例如:同时打开多个聊天窗口;迅雷同时下载多个文件
单线程:同一时刻,只允许执行一个线程
多线程:同一时刻,可以执行多个线程
并发:同一时刻,多个任务交替执行,造成一种“貌似同时”的错觉,即单核CPU执行多任务
并行:同一时刻,多个任务同时执行,多核CPU实现同行。即多核CPU执行的多任务
创建线程的两种方式:
方式一:继承Thread类
class Cat extends Thread {
// 在run方法中,重写自己的业务代码
@Override
public void run() {
int times = 0; // 记录输出次数
while (true) {
// 每隔1秒钟,输出“喵喵,小猫咪”。输出80次后自动退出
// Thread.currentThread().getName():获得该线程的名字
System.out.println("线程名字" + Thread.currentThread().getName()); // Thread-0
System.out,println("喵喵,小猫咪");
// 休眠1s,会抛出异常使用try-catch
try {
Thread.sleep(1000); // 1000ms = 1s
} catch (InterruptedException e) {
e.printStackTrace();
}
if (times == 80)
break;
}
}
}
方式二:实现Runnable接口
class Dog implements Runnable {
@Override
public void run() {
int count = 0;
while (true) {
// 每隔1s,输出“小狗汪汪叫”。输出80次后自动退出
System.out.println("线程名字: " + Thread.currentThread().getName()); //Thread-0
System.out.println("小狗汪汪叫~~");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (count == 80)
break;
}
}
}
// 开启线程
Cat cat = new Cat();
cat.start();
线程执行分析:
1.开始执行程序代码时,就相当于开启了一个线程
2.程序开始执行main方法,就相当于开启了一个线程 -- main线程
3.类A继承Thread类或实现Runnable接口就相当于线程类
4.main方法中创建A类对象就相当于创建了一个线程,而调用其start()方法相当于开启了线程
5.此时main线程与A线程(Thread-0)同时执行,多核CPU实现了同行
源码解读:
执行start方法
public synchronized void start() { start0(); }
进而继续调用start0方法
private native void start0();
// 该方法是本地方法,native,底层由JVM实现调用,通过C/C++编写
注意:真正实现多线程效果的是start0方法,不是run方法也不是start方法。
终止线程:
1.线程完成任务后自动退出
2.通知线程退出:使用变量控制run方法退出
// 线程类
class T extends Thread {
private int count = 0;
// 设置一个控制变量,控制线程是否退出
private boolean loop = true;
@Override
public void run() {
while (loop) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T线程运行..." + (++count));
}
}
public void setLoop(boolean loop) {
this.loop = loop;
}
}
// main方法
public static void main(String[] args) throws InterruptedException {
T t = new T();
t.start();
// 在main线程中控制t线程
// 先让main线程休眠10s
System.out.println("main线程休眠中....");
Thread.sleep(10 * 1000);
// 设置控制变量,终止t线程
t.setLoop(false);
}
线程状态:
Thread类中存在:public static enum Thread.state
1.new:尚未启动的线程出于此状态
2.Runnable:在Java虚拟机中执行的线程处于此状态
Ready:线程就绪;Running:线程执行 (线程是否执行取决于是否被调度器选中)
3.Blocked:被阻塞等待监视器锁定的线程出于此状态
4.Waiting:正在等待另一线程执行特定动作的线程出于此状态
5.Timed_Waiting:正在等待另一个线程那个执行指定动作达到等待时间的线程处于此状态
6.Terminated:已退出的线程处于此状态
线程的状态转换:
线程被创建后处于new状态,后调用start方法启动线程,线程处于Runnable状态
线程在Runable状态下,执行sleep(time)、wait(time)等方法进入TimeWaiting状态
通过时间结算,到达指定时间重新回到Runable状态
线程在Runable状态下,执行wait()、t.join()、LockSupport.park()等方法进入waiting状态
后调用notify()、notifyAll()、LockSupport.unpark()重新回到Runable状态
线程在Runable状态下,等待进入同步代码块的代码锁,进入Blocked状态
得到锁后,重新回到Runable状态
线程在Runable状态下,被调度器选中执行进入Running;被挂起或调用yield()进入Ready
线程执行完成,进入Terminated状态
查看线程状态:getState()方法