多线程知识点

1.多线程



例如:一个短视频,一个线程复制管理视频,一个线程负责管理声音,一个线程负责管理弹幕
进程:Process,程序一旦开始运行就是是一个进程
线程:Thread,一个程序运行后,里面就包含了多个线程

真正的多线程是指有多个cpu,即多核。如果是模拟的多线程,即只有一个cpu,在同一时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错误

2.线程的创建

1.继承Thread类
线程不一定立即执行,听从cpu的安排,交替执行

bash 复制代码
//实现步骤
1.继承Thread
2.重些run方法
3.对象. start()启动线程
public class StartThread extends Thread
{
@Override
public void run()
{
}
}
StartThread a=new StartThread();
a.start()

2.实现Runnable接口
接口实现类对象能被多个线程使用

1.实现接口

2.编写线程方法

3.开启线程,通过实现Runnable接口来创建线程,启动线程时需要通过Thread对象。

bash 复制代码
PrimeRun p = new PrimeRun(143);
new Thread(p).start();

并发问题:

3.实现Callable接口

3.静态代理

使用步骤

1.需要代理对象、实际对象,以及一个抽象接口

2.代理对象、实际对象都要实现接口

3.代理对象中创建构造方法,方法参数为接口类对象

4.在代理对象中定义抽象接口类对象来接收构造方法的参数对象

5.在代理对象中接口的实现方法中,用接收到的变量接口对象调用实现的接口方法
逻辑,通过代理对象的有参构造,将实际对象以参数的形式传递到代理类中,然后在代理类接口的实现方法中,调用实际类中的实现方法

4.线程停止

1.设立外部标志位,定义一个公开的方法,通过改变标志位来结束进程

5.线程休眠

应用

1.模拟网络延时
通过延时可以发现多线程中出现的问题,如数据同步性
2.倒计时
每个对象都有一把锁,sleep不回释放锁

6.线程礼让

Thread.yield()
正在进行的线程,由运行态转为就绪态,然后由cpu在就绪态中选择另一个线程,礼让不一定百分百成功

7.线程强制执行

线程插队,强制执行插队的线程

8.观测线程的状态

Thread.getState()
线程的状态

1.创建

2.就绪

3.执行

4.阻塞

5.结束,线程一旦结束,就不能再被使用

9.线程的优先级

thread.setPriority()

10.守护线程

监控用户线程,用户线程结束,守护线程也结束
thread.setDaemon()

11.线程同步

并发:同一个对象被多个线程同时操作,如:秒杀,抢票
解决线程的不安全性:队列+锁,解决数据安全性
synchronized

bash 复制代码
//修饰代码块
synchronized(this){} //修饰当前类
synchronized(类.class){}//修饰其他类
//修饰方法
1.修饰静态方法
2.修饰非静态方法

案例代码:
class Thick implements Runnable
{
    private int num=10;
    Boolean flag=true;


    @Override
    public void run()
    {
        try {
            buy();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void buy() throws InterruptedException {
        while (flag)
        {
            Thread.sleep(200);
            if (num>0)
                synchronized (this)
                {
                    System.out.println(Thread.currentThread().getName()+"买到了第"+num--+"票");
                }
            else
            {
                flag=false;
            }
        }
    }
    
 public class CarThick {
    public static void main(String[] args) {
        Thick thick=new Thick();
        new Thread(thick,"张三").start();
        new Thread(thick,"李四").start();
        new Thread(thick,"王二狗").start();
    }
}

12.死锁

13.Lock锁

synchronized锁的作用一样,在线程同步的情况下,保证数据的原子性

bash 复制代码
ReentrantLock//可重入锁
private final ReentrantLock lock=new ReentrantLock();
lock.lock();//加锁,在数据发生改变的地方,加锁
lock.uplock;//解锁,完成数据改动后,把锁给下一个线程

14.生产者与消费者-线程通信

1.生产者
2.消费者
3.线程池
4.消费品

管程法

bash 复制代码
//线程池
class SynContainer{
    // 需要一个容器大小
    Bug[] bugs = new Bug[10];
    // 容器计算器
    int count = 0;

    // 生产者放入bug
    public synchronized void push(Bug bug){
        // 如果容器满了,就需要等待消灭bug
        if(count==bugs.length){
            // 通知消灭bug者消灭,生产bug等待
            try {
                //导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
                this.wait();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 如果没有满,我们就需要继续生产bug
        bugs[count] = bug;
        count++;

        // 可以通知消灭者消灭了
        this.notifyAll();
        // notifyAll唤醒正在等待对象监视器的所有线程。
    }

    // 消灭者消灭bug
    public synchronized Bug pop(){

        // 判断能否消灭
        if (count == 0){
            // 等待生产者生产,消灭者等待
            try {
                this.wait();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 如果可以消灭
        count--;
        Bug bug = bugs[count];

        // 消灭完了,通知生产者生产

        this.notifyAll();
        try {
            System.out.println("通知生产者");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return bug;

    }
//生产者
class Productor extends Thread{

    SynContainer container;

    public Productor(SynContainer container){
        this.container = container;
    }

    // 生产
    @Override
    public void run() {
        for (int i = 0; i <=100; i++) {
            container.push(new Bug(i));
            System.out.println("生产了"+i+"个bug");
        }
    }
}

//消费者
class Consumer extends Thread{

    SynContainer container;

    public Consumer(SynContainer container){
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            System.out.println("消灭了-->"+container.pop().id+"个bug");
        }
    }
}
//消费品
class Bug{
    int id;// bug编号
    public Bug(int id){
        this.id = id;
    }
}
//测试
public class ProviderAndConsumer
{
    public static void main(String[] args) {
        SynContainer container = new SynContainer();
        new Productor(container).start();
        new Consumer(container).start();
    }
}

15.线程池

避免重复的创建销毁线程,减少资源浪费,类似于数据库连接池

相关推荐
原野心存1 分钟前
java基础进阶——继承、多态、异常捕获(2)
java·java基础知识·java代码审计
进阶的架构师6 分钟前
互联网Java工程师面试题及答案整理(2024年最新版)
java·开发语言
黄俊懿6 分钟前
【深入理解SpringCloud微服务】手写实现各种限流算法——固定时间窗、滑动时间窗、令牌桶算法、漏桶算法
java·后端·算法·spring cloud·微服务·架构
易辰君8 分钟前
python爬虫 - 深入requests模块
开发语言·爬虫·python
木子020414 分钟前
java高并发场景RabbitMQ的使用
java·开发语言
无夜_15 分钟前
Prototype(原型模式)
开发语言·c++
看到请催我学习16 分钟前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript
夜雨翦春韭26 分钟前
【代码随想录Day29】贪心算法Part03
java·数据结构·算法·leetcode·贪心算法
大霞上仙1 小时前
jmeter学习(1)线程组与发送请求
java·学习·jmeter
笃励1 小时前
Java面试题二
java·开发语言·python