1.进程
1.1 概念
进程:程序运行时,系统会开辟的一块空间给这个程序,这个空间就是进程
线程:是进程中的单个顺序控制流,是一条执行路径。
并行(多线程):单位时间片内,所有任务“可能”同时执行。意思是多线程在运行时,CPU在线程中随机切换,
并发(单线程):单位时间片内,任务交替执行。意思是一个任务在执行的时候,其他的任务是不可以执行的,
必须等这个任务执行完才能进行下一个任务。(Java是基于并发的)
**CPU在不断地做高速切换线程的动作
1.2 实现多线程的方式1---Thead的实现类
方法:run() 在线程开启后调用次方法,相当于普通的调用方法
start() jvm虚拟机调用run方法,jvm会帮我们开启一条执行路径。这个才是开启线程的
1.3 实现步骤
1.定义一个类MyThread继承Thread类
2.在MyThread类中重写run()方法
3.创建MyThread类的对象
4.调用start方法启动线程
1.3 设置和获取线程名称的方法
setName(String name)----->设置线程名称
getName()----->获取线程名称
Thead currentThead().getName()----->返回正在执行线程对象的引用(意思就是返回主线程的名字)
线程的优先级:
java使用的是抢占式调度模式。
final void setPriority(int newPriority)------>设置线程的优先级
final int getPriority()----->获取线程优先级 (默认为5)
final int getPriority(Thread.MAX_PRIORITY )----->获取线程最大优先级数
final int getPriority(Thread.MIN_PRIORITY )----->获取线程最小优先级数
线程数为1-10;
static void sleep()------>使正在运行的线程暂时处于休息状态,暂时没有抢夺CPU的权利
void.join()----->等待这个线程执行完毕,其他的才会执行
void SetDaemon()------>将线程设置为守护线程,(意思就是主线程死亡,他就会随着主线程死亡,但并不是立即就结束)
1.4 线程的六种状态
NEW (创建了线程对象,但是还没有调用start方法)
至今尚未启动的线程处于这种状态。
RUNNABLE(CPU正在执行该线程的状态)
正在 Java 虚拟机中执行的线程处于这种状态。
BLOCKED(阻塞,其实就是有资格抢夺cpu执行权的线程,一种没有抢到的状态)
受阻塞并等待某个监视器锁的线程处于这种状态。
WAITING(无限等待, 遇到了"锁对象"的wait方法,此时已经失去了抢夺权)
无限期地等待另一个线程来执行某一特定操作的线程处于这种状态。
TIMED_WAITING(计时等待, 遇到了sleep,此时已经失去了抢夺权)
等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态。
TERMINATED(死亡状态)
已退出的线程处于这种状态。
2. 使用匿名内部类实现线程
实现代码:
public class Test03 {
public static void main(String[] args) {
//匿名内部类实现线程
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}
}).start();
}
}
3. 同步代码块
卖票的案例 (代码在Day11项目下,BookingDemo中)
卖票案例中出现的问题:
1.出现重复卖同一张票的情况
2.出现了卖负号票的情况
解决方案:(同步代码块)使用最多
sychronized(锁对象){
方法体 //被锁对象锁住的东西,只有这条线程执行完了,其他的线程才会进来
}
锁什么时候打开:执行到sychronized的左边的“{”时打开
锁什么时候关闭:执行到sychronized的右边的“}”时关闭
·注意
·同步的好处和弊端
*好处:解决了多线程的数据安全的问题
*弊端:当有很多线程时,每个线程都有锁,都运行的时候需要判断锁的状态,很耗费资源,运行效率就会降低
代码案例:
/*
一共100张票,3个窗口同时出售
*/
子类
public class SeilTicket implements Runnable {
private int number =100;
@Override
public void run() {//重写run方法,实现3条线程同时执行
while (true) {
//添加同步代码块 ,this可以也可以换成o。(在上面定义一个Object o=new Object)
synchronized (this) {
//判断剩余的票是否大于等于0
if (number <= 0) {
break;//票数小于0,表示没有票了
}
//使用sleep修改毫秒值
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卖出去一张票,number就-1;
number--;
System.out.println(Thread.currentThread().getName() + "卖出去一张票,还剩" + number + "张票");
}
}
}
}
测试类
/*
一共100张票,3个窗口同时出售
*/
public class MaiPiaoDemo {
public static void main(String[] args) {
//创建实现类对象
SeilTicket ticket = new SeilTicket();
//设置3个窗口进行卖票
Thread t1 = new Thread(ticket,“窗口1”);
Thread t2 = new Thread(ticket,“窗口2”);
Thread t3 = new Thread(ticket,“窗口3”);
//启动线程
t1.start();
t2.start();
t3.start();
}
}
##公交车案例
/*
需求:
模拟有一个公交车上车的乘客和下车的乘客,一次上一个,一次下一个 交替执行
最多可上30人。
思路:
1.先定义一个bus类,定义一个变量乘客passenger;
2.定义一个上车和下车线程,重写Thead的run方法
3.用同步代码块把上车,下车的方法体包起来,用this锁锁起来,要判断上车不能超过30人,下车不能少于0人
4.用.wait等待线程,用this.notify唤醒其他线程
5.创建测试类,定义bus对象 ,用匿名内部类启动线程
*/
·Bus类
public class Bus {
private int passenger=0;
//上车线程
public void getOn() {
//用同步代码块
synchronized (this) {
//判断当前车上是否为30人
if (passenger >= 30) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
passenger++;
System.out.println("上车1人,当前车上" + passenger + "人");
//唤醒下车线程
this.notify();
}
}
//下车线程
public void debus() {
//同步代码块
synchronized (this) {
//判断车上人数是否为0
if (passenger <= 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
passenger--;
System.out.println("下车1人,当前车上" + passenger + "人");
//唤醒上车线程
this.notify();
}
}
}
·测试类
public class Test {
public static void main(String[] args) {
//创建bus对象
Bus bus = new Bus();
new Thread(){
@Override
public void run() {
//用while循环上车线程
while (true){
bus.getOn();
}
}
}.start();//启动线程
new Thread(){
@Override
public void run() {
//用while循环上车线程
while (true){
bus.debus();
}
}
}.start();//启动线程
}
}
公交车升级版
·BusPlus类
package com.BusDemo;
import java.util.Random;
/*
公交车案例升级版
随机获得上车人数和下车人数
*/
public class BusPlus {
//定义乘客变量
private int passager;
//上车线程
public void geton1(){
//同步代码块
synchronized (this){
//判断人数是否超过30人
if(passager>=30){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//获取随机上车人数
Random r = new Random();
//随机数的范围是最多30人减去车上现在的人数,在加1,因为范围是从0开始的
int person = r.nextInt(30 - passager) + 1;
passager+=person;
System.out.println(“上车”+person+“人,现在车上一共”+passager+“人”);
this.notify();//唤醒下车线程
}
}
//下车线程
public void debus1(){
//同步代码块
synchronized (this){
//判断现在车上人数是否少于0
if(passager<=0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//随机获取下车人数
Random r = new Random();
int person = r.nextInt(passager) + 1;
passager-=person;
System.out.println(“下车”+person+“人,现在车上一共”+passager+“人”);
this.notify();
}
}
}
·测试类
public class TestPlus {
public static void main(String[] args) {
BusPlus bus1 = new BusPlus();
new Thread() {
@Override
public void run() {
while (true) {
bus1.geton1();
}
}
}.start();
new Thread() {
@Override
public void run() {
while (true) {
bus1.debus1();
}
}
}.start();
}
}