线程的概述
1.什么是进程?
正在运行的程序叫进程!
2.OS为每个进程分配内存
进程之间没有共享数据,都有自己独立的内存可以使用。
3.进程的代码谁来执行
进程中执行代码的是线程
4.进程中同时执行的多个任务
就是多线程。
如果进程中只有一个任务需要执行,那么就是单线程了。
5.线程的概念
进程在执行过程中,可能需要多个任务同时执行,每个任务的执行者就是线程。线程 就是进程中的一个执行控制单元。
6.多线程的用途
同时执行多个任务,可以提高效率。
可以完成多个任务并发的效果。
7.JVM是一个进程,它也是多线程的。一个主线程需要去执行main,还要有一个线程去执行垃圾回收工作。
8.线程是部分,进程是整体
线程是部分,部分不能单独存在,它依赖与进程(整体)。
线程不能单独启动,而进程可以。
一个进程中的多个线程可以共享数据,而进程与进程之间不会共享数据。
创建多线程方式一:继承Thread类
1.怎么写一个多线程程序
1 给线程添加任务
为?Thread类写一子类,并重写父类的run()方法。
2 创建子类对象
3 调用子类对象的start()方法。;
2.多个进程同时运行是假的!多个线程同时运行也是假的!
3.线程的随机性,以及时间分片
CPU不是按顺序给线程插电,而是随机的。
CPU会给一个线程插电之后,只给一小段时间,如果这个时间用完了,那么就拔电!不
同的OS时间分的长短不一样。
通常一个线程在没有用完时间片时就主动休眠了
4.同一个多线程程序多次运行,结果可能不一样
就是因为线程的随机性!就是CPU就是这么随机的,没有顺序的!
5.主线程结束时,JVM是否结束
当主线程结束时,其他还有线程还没结束,那么JVM是否结束。
只要有线程,那么JVM就不会结束。
线程状态
1.线程的生命周期包含状态
新状态:
Thread th = new Thread();
th就是新状态。在th还没有被调用start()方法之前它是新状态!
就绪状态(可运行状态)
th.start()就绪状态。
就绪状态包含了运行状态。你有可能是在运行,也有可能等待着CPU来插电!
运行状态
CPU给你插电了,你就运行了。
运行的线程最好去主动进入阻塞状态。这样不用时间片用完了就可以给你断电了。
阻塞状态
休眠:Thread.sleep()方法时,那么这个线程就进入了休眠状态,它如果想回到就
绪状态就必须睡足了指定的时间。
等待:wait(),当一个线程执行了wait()方法后,那么它就进入了一个监视器对象
的等待列表中,这时它再也醒不过来了,只能等待另一个线程去唤醒它。
挂起: 当调用线程对象的suspend()方法后,这个线程就挂起了,要想回到就绪需要
调用这个线程的resume()就回到了就绪状态。但suspend()和resum()都过时了。
IO阻塞:当一个线程在进入IO操作时,那么就一定要等待到IO操作完毕才能回到就 绪状态。
锁定:当一个线程想上厕所,但厕所有人,那么这个线程锁定了。这个线程需要等
待到前一个线程释放对象锁,然后这个线程获取到了对象锁才能回到就绪状态。
死亡状态
正常死亡:当run()方法结束了,线程就死了。
非正常死亡:因为没有抓捕到的异常导致线程突然死亡。只能是RuntimeExeption
被杀了:有人调用了线程的stop()。这个方法已经被作废了,你不应该去使用它。
创建多线程方二:实现Runnable接口
Runnable接口有一个run()方法,它是很简单的东西。实现它只需要重写run()方法就可以了。
因为Runnable接口不是Thread类,所以这时想获取当前线程需要使Thread.currentThread()。
实例:
售票
实现多窗口同时售票!
多个窗口共享同一票库,当票库无票时,程序结束。
public class Test {
public static void main(String[] args) {
PiaoKu pk = new PiaoKu(100);
// 四个窗口共享一个票库
ChuangKou ck1 = new ChuangKou(pk);
ChuangKou ck2 = new ChuangKou(pk);
ChuangKou ck3 = new ChuangKou(pk);
ChuangKou ck4 = new ChuangKou(pk);
Thread th1 = new Thread(ck1, "a");
Thread th2 = new Thread(ck2, "b");
Thread th3 = new Thread(ck3, "c");
Thread th4 = new Thread(ck4, "d");
th1.start();
th2.start();
th3.start();
th4.start();
}
}
// 售票窗口
class ChuangKou implements Runnable {
private PiaoKu pk;//每个窗口都需要有一个票库
// 创建窗口时给窗口传递一个票库对象
public ChuangKou(PiaoKu pk) {
this.pk = pk;
}
public void run() {
String name = Thread.currentThread().getName();
while(true) {
//当票库的票数小于等于0时,跳出循环。
if(pk.getCount() <= 0) {
break;
}
try {
Thread.sleep(20);
} catch (InterruptedException e) {
}
// 出票,并打印票码
System.out.println(name + ": " + pk.chuPiao());
}
}
}
// 票库
class PiaoKu {
private int count;
public PiaoKu(int count) {
this.count = count;
}
// 获取当前票库的票数
public int getCount() {
return count;
}
// 出票,在出票同时还会返回当前出的是倒数第几张
public int chuPiao() {
int cnt = this.count--;
return cnt;
}
} |