Java多线程基础

相关概念

程序:指令的集合(代码)

进程:是程序的一次执行过程,包括产生、存在和消亡的过程

线程:是进程的一个实体,一个进程可以拥有多个线程。

单线程:同一时刻,只允许执行一个线程。

多线程:同一时刻,可以执行多个线程。

并发:同一时刻,多个任务交替执行,单核CPU(人脑)

并行:同一时刻,多个任务同时执行,多核CPU

创建线程的两种方式

继承Thread类,重写run方法

class Cat extends Thread {
	@Override
    public void run() {//重写run方法,写上自己的业务逻辑
        while (true) {
            //该线程每隔1秒在控制台输出“瞄瞄,我是小猫咪"”
            system.out.println("瞄瞄,我是小猫咪");
            //让该线程休眠1秒
            try {
            	Thread.sleep(1000);
            }catch (InterruptedException e) {
            	e.printStackTrace();
            }
        }
    }
}
public class Thread01 {
    public static void main(String[] args) {
        //创建Cat对象,可以当做线程使用
        Cat cat = new Cat();
        cat.start();//启动线程,主线程不会阻塞,与子线程交替执行
    }
}

为什么是调用start而不是run方法

调用start方法才是开辟子线程,直接调用run方法则是在主线程中顺序执行

实现Runnable接口,重写run方法(推荐)

因为Java是单继承的,某些情况下一个类可能已经继承了某个父类,所以可以通过实现Runnable接口

此外,该方式比较适用于多个线程共享资源的情况

public class Thread02 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        //dog.start();这里不能调用start
        Thread thread1 = new Thread(dog);
        thread1.start();
    }
}

使用了设计模式——(静态)代理(Proxy)模式

多线程

不同线程完成不同的事

多线程售票:

出现了票数为负的情况

线程终止

1、自动退出

2、通知方式:通过使用变量来控制run方法退出

重写run方法的类中设置一个控制变量作为run方法中循环体的循环条件,并设置set方法,破坏循环条件退出run方法从而终止线程

线程状态

1、NEW新建状态

2、RUNNABLE可运行状态

3、BLOCKED阻塞

4、WAITTING等待

5、TIMED_WAITTING超时等待

6、TERMINATED终止

线程同步synchronized(加锁)

多线程编程中,内存中一些敏感数据不允许被多个线程同时访问,此时就使用同步技术,保证内存地址在同一时刻,最多被一个线程访问,以保证数据的完整性。

使用synchronized修饰方法,称为同步方法,run()中调用该同步方法。

1、同步方法如果没有使用static修饰:默认锁对象为this

2、如果方法使用static修饰,默认锁对象:当前类.class

或选择同步代码块(推荐)

@Override
public void run() {
    while(true){
        synchronized (this) {//object是锁
    		//同步代码
		}
    }
}

同步原理

互斥锁:每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

要求多个线程的锁对象为同一个

释放锁:执行完毕释放

例题:

(1)在main方法中启动两个线程

(2)第1个线程循环随机打印100以内的整数

(3)直到第2个线程从键盘读取了“Q”命令。

class A extends Thread {
    private boolean loop = true;
    
    @Override
    public void run() {
        //输出1-100数字while (loop) {1
        system.out.println((int)(Math .random() * 100 + 1));
        //休眠
        try {
        	Thread.sleep(1000);
        }catch (InterruptedException e) {
        	e.printStackTrace();
        }
    }
    
    public void setLoop(boolean loop) {
    	this.loop = loop;
    }
}

class B extends Thread {
    private A a;
    
    private Scanner scanner = new Scanner(System.in);
    
    public B(A a){//构造器中,直接传入A类对象
    	this.a = a;
    }
    
    @Override
    public void run() {
        while (true) {
            //接收到用户的输入
            System.out.println("请输入你指令(Q)表示退出: ");
            char key = scanner.next().toUpperCase().charAt(0);
            if(key == 'Q') {
                //以通知的方式结束a线程
                a.setLoop(false);
                System.out.printLn("b线程退出");
                break;
        	}
    	}
    }
}

public class test01 {
    public static void main(String[] args) {
        A a = new A();
        B b = new B(a);//一定要注意
        a.start();
        b.start();
    }
}
posted @   上瘾了  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
点击右上角即可分享
微信分享提示