day21

day21

一、线程

1.程序:一个固定逻辑与数据的集合就叫程序  例子:贪吃蛇
2.cpu:中央处理器  用来协调程序与硬件的工作
3.并发与并行:
	并发(高并发):在同一个时间,执行两个或者两个以上的程序,单核cpu交互执行
		(误区:不是同时执行,是交替执行)
	并行:在同一时刻,执行两个或者以上的程序的时候,多核cpu一起执行 (目前的电脑都是多核的)

在这里插入图片描述

4.进程和线程:
	进程:运行在内存中的程序叫进程 例子:idea
	线程:通向cpu的执行路径叫线程
5.分类:
	单线程:只有一条通向cpu的执行路径
	多线程:多条通向cpu的执行路径

单线程:
在这里插入图片描述

多线程:
在这里插入图片描述

1.1 主线程:

在这里插入图片描述

1.2 线程的第一种创建方式
1.创建的步骤:
	A.定义一个类继承:Thread
	B.重写run()方法,执行线程操作
	C.实例化这个线程的对象
	D.调用Start()方法开启线程

代码 -测试类:

package com.lt.demo11;

public class Teat01 {
    public static void main(String[] args) {
        MyThread m = new MyThread();
        m.start();
    }
}

代码-定义类:

package com.lt.demo11;

public class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

1.3 线程的调度方法
1.线程的配调的方式:分配式调度和抢占式调度
2.分配式调度:多个线程执行任务的时间,都是平均分配的,每一个线程执行的时间都是相等的
3.抢占式调度:线程的优先级越高,抢占cpu的执行权越高,线程抢到cpu的执行权,优先执行
	注意点:Java的多线程就是抢占式调度(比武招亲)

原因分析:

在这里插入图片描述

1.4 线程的内存图:

在这里插入图片描述

二、线程的方法

2.1 线程的一些方法
1.获取线程的名称的方法:
	public final String getName()   返回该线程的名称
	public static Thread currentThread()   返回对当前正在执行的线程对象的引用
2.改变线程的名称的方法;
	 public final void setName(String name) 改变线程名称
	 public Thread(String name)   	通过构造方法设置线程的名称(这个Thread里面需要有参构造)
3.线程休眠的方法:
	public static void sleep(long millis)   设置线程休眠,时间单位是毫秒
4.守护线程:
	A.守护其他线程  守护其他线程执行完操作(Java里面的gc垃圾回收器就是一个守护线程)
	B.守护线程的死亡:被守护的线程执行完操作或守护的线程死亡,那么守护线程才会死亡
	C.一般的守护线程都是守护主线程
5.线程的优先级:
	常量:
		A.public static final int MAX_PRIORITY  线程可以具有的最高优先级
		B.public static final int MIN_PRIORITY   线程可以具有的最低优先级
		C.public static final int NORM_PRIORITY  分配给线程的默认优先级
	注意点:1.线程的最高优先级是10  最低优先级是1 范围:1-10
			2.线程优先级越高表示线程抢到了,但是不一定执行

在这里插入图片描述

2.2 线程的第二种创建方式
1.步骤:
	A.定义一个类,实现Runnble接口
	B.实现里面的run()方法
    C.实例化线程对象:Thread 传递一个参数Runnble的实现类	

测试类:

package com.lt.demo10;

public class Test01 {
    public static void main(String[] args) {
        //实例化MyRunnble类
        MyRunnble m = new MyRunnble();

        //实例化Thread类
        Thread t = new Thread(m);
        t.start();
    }
}

定义类:

package com.lt.demo10;

public class MyRunnble implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

2.3 使用内部类里创建线程
package com.lt.demo10;

public class Test02 {
    public static void main(String[] args) {

        //第一种方法
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }).start();

        //第二种方法
        new Thread(){
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }.start();

    }
}

三、线程通信(重点)

3.1 案例:

在这里插入图片描述

需求分析:

A.每一个窗口就是一个线程 使用线程来表示多窗口售票
B.数据共享 使用第二种方式来创建线程 
C.定义一个变量来表示票数
D.循环售票

定义类:

package com.lt.demo12;

public class MyRunble  implements Runnable{
    //定义一个数来表示票的数量
    private  int count=100;

    @Override
    public void run() {

        while (count>=0){
            if (count>0){
                System.out.println(Thread.currentThread().getName()+"\t"+count);
                count--;
            }
        }
    }
}

测试类:

package com.lt.demo12;

public class Test01 {
    public static void main(String[] args) {
        MyRunble r =new MyRunble();
        //第一个线程
        Thread t1 = new Thread(r);
        t1.start();

        //第二个线程
        Thread t2 = new Thread(r);
        t2.start();

        //第三个线程
        Thread t3 = new Thread(r);
        t3.start();
    }


}

上面的代码出现错误:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4FIRmp8Y-1646738793683)(C:/Users/%E6%82%B2%E9%99%8C/AppData/Roaming/Typora/typora-user-images/image-20220308184136814.png)]

产生问题原因:

在这里插入图片描述

3.2 第一种解决方法:同步代码块
1.语法:
	synchronized(锁对象){
		可能发生错误的代码
	}
2.注意点:
	A.锁对象可以是任意的对象
	B.所有的线程锁的对象必须是同一个是对象
3.作用:
	解决数据共享安全问题

优化代码:

package com.lt.demo12;

public class MyRunble  implements Runnable{
    //定义一个数来表示票的数量
    private  int count=100;

    //定义一个锁对象
    private Object obj = new Object();

    @Override
    public void run() {
        while (count>=0){
         synchronized (obj){
             if (count>0){
                 System.out.println(Thread.currentThread().getName()+"\t"+count);
                 count--;
             }
         }
        }
    }
}

测试类不变

3.3 解决问题分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9BqrNMWl-1646738793685)(C:/Users/%E6%82%B2%E9%99%8C/AppData/Roaming/Typora/typora-user-images/image-20220308185059261.png)]

3.4 第二种方法-同步方法
1.语法:
	访问修饰符  synchronized  返回值类型 方法的名称(参数列表){
		方法体
		return 返回值
	}
2.说明:同步方法可以是普通的方法,也可以是静态的方法
3.解释:
	A.成员方法的锁的1对象是this
	B.静态方法的锁的对象是当前类的class对象

优化代码:

package com.lt.demo12;

public class MyRunble  implements Runnable{
    //定义一个数来表示票的数量
    private static int count=100;

    //定义一个锁对象
    private Object obj = new Object();

    @Override
    public void run() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        while (count>=0){
            showInfo();

        }
    }

    public static synchronized void showInfo(){
        if (count>0){
            System.out.println(Thread.currentThread().getName()+"\t"+count);
            count--;
        }
    }
}

测试代码不变

3.5 第三种解决方法
1.使用Lock(接口)
	A.Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。
	B.此实现允许更灵活的结构
2.实现类:ReentrantLock
3.方法:
	void lock()  获取锁
	void unlock()  释放锁

优化的代码:

package com.lt.demo12;

public class Test01 {
    public static void main(String[] args) {
        MyRunble r =new MyRunble();
        //第一个线程
        Thread t1 = new Thread(r);
        t1.start();

        //第二个线程
        Thread t2 = new Thread(r);
        t2.start();

        //第三个线程
        Thread t3 = new Thread(r);
        t3.start();
    }


}

四、死锁

1.死锁:A占用B的锁对象 B占用A的锁对象 互不谦让 两个现场1处于等待状态,形成死锁
2.例子:
	两个人在寝室,宿舍里只有一双拖鞋,A占领左拖鞋,B占领右拖鞋 两个人都要出去买东西,两个都不给对方另外一只拖鞋,都出不去

A成员:

package com.lt.demo13;

public class AMyRunnble implements Runnable {
    @Override
    public void run() {
        synchronized (Shoe.LEFT){
            System.out.println("A占领左拖鞋");
            synchronized (Shoe.RIGHT){
                System.out.println("A占领右拖鞋");
            }
        }
    }
}

B.成员:

package com.lt.demo13;

public class BMyRunnble implements Runnable {
    @Override
    public void run() {
        synchronized (Shoe.RIGHT){
            System.out.println("B占领右拖鞋");
            synchronized (Shoe.LEFT){
                System.out.println("B占领左拖鞋");
            }
        }
    }
}

定义类:

package com.lt.demo13;

public class Shoe {
    public static final String LEFT="LEFT";
    public static final String RIGHT="RIGHT";
}

测试类:

package com.lt.demo13;

public class Test01 {
    public static void main(String[] args) {
        //实例化A成员
        AMyRunnble amy = new AMyRunnble();
        Thread t1 = new Thread(amy);
        t1.start();

        //实例化B成员
        BMyRunnble bmy = new BMyRunnble();
        Thread t2= new Thread(bmy);
        t2.start();
    }
}

测试结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GcPNEPth-1646738793686)(C:/Users/%E6%82%B2%E9%99%8C/AppData/Roaming/Typora/typora-user-images/image-20220308192407454.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个胖小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值