这篇多线程知识你真得好好看看,阿里,字节跳动,美团的面试官都喜欢问

235 篇文章 4 订阅

Java线程

1.进程和线程

进程:程序运行依赖一个或多个线程
线程:进程运行依赖多个线程,线程是操作系统能够调度的最小单位

2.并发和并行

并发:一个CPU同时执行多个程序
并行:多个CPU同时执行多个程序

3.线程的状态/线程的生命周期

1)新建状态(New):new对象是为新建状态
2)就绪状态(Runnable):调用start()方法后为就绪状态,该线程已准备就绪,等待CPU的调度执行,就绪状态是运行状态的唯一入口
3)运行状态(Running):就绪状态的线程得到CPU的调度执行
4)阻塞状态(blocked):运行状态的线程失去CPU的执行,挂起等待再次进入就绪状态
5)终止状态(Dead):线程执行完毕或者异常退出run()方法,线程的生命周期结束

阻塞状态有三种:

(1)运行阻塞:线程执行wait()方法
(2)同步阻塞:线程获取synchronized同步锁失败,进入同步阻塞状态
(3)其他阻塞:通过调用线程的sleep()、join()、或者I/O请求时,会进入阻塞状态,等待sleep()超时、join()线程终止或超时、或者I/O请求处理完毕时,线程重新进入就绪状态

多线程例子

继承Thread类

public class MyThread {
    public static void main(String[] args) {
        Thread1 t1 = new Thread1();
        Thread1 t2 = new Thread1();
        Thread1 t3 = new Thread1();
        t1.setName("a");
        t2.setName("b");
        t3.setName("c");
        t1.start();
        t2.start();
        t3.start();
    }
}
//解决线程问题可选方法同步锁
class Thread1 extends Thread {
    //num>50时,多个线程对50进行减1
    //int num=50;   继承Thread类实现多线程,每一次new创建实例都会 初始化实例变量num,
    // 最终运行是每一个线程的num初始为50
    //加入static修饰成为静态变量
    static int num = 50;

    @Override
    public void run() {
        while (true) {
            if (num > 0) {
                try {
                    //出现0,-1等情况,在num--前,多个线程进行了num判断
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //出现重复的num,情况与上例相似,在num--前,有多个线程进行了输出
                System.out.println(getName() + ",num = " + num--);
            }else {
                break;
            }
        }
    }
}

实现接口Runnable


public class MyRunnable {
    public static void main(String[] args) {
        Thread2 runnable = new Thread2();
        Thread t1 = new Thread(runnable,"a");
        Thread t2 = new Thread(runnable,"b");
        Thread t3 = new Thread(runnable,"c");
        t1.start();
        t2.start();
        t3.start();
    }
}
//问题1:
//Runnable接口实现的num--,全部重复3次,问题?
class Thread2 implements Runnable{
	int num = 50;
    @Override
    public void run() {
        //int num = 50; 变量写在了run()方法里,每个线程实例变量都为50
        while (true) {
            if (num > 0) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " num = " + num--);
            } else {
                break;
            }
        }
    }
}

问题1:实现Runnable接口,同一个实例,为什么变量不共享?

答:变量的位置写在了run()方法里,每个线程执行都是新的实例变量

线程使用同步锁解决线程安全问题

public class Thread2 implements Runnable {
    int num = 50;
    //Object object = new Object();

    @Override
//    synchronized public void run() {
    public void run() {
        while (true) {
//            synchronized (object) {
            synchronized (this) {
                if (num > 0) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " num = " + num--);
                } else {
                    break;
                }
            }
        }
    }
}

继承Thread类,线程上锁

静态资源上锁,上锁对象 类.class

//解决线程问题可选方法同步锁
class Thread1 extends Thread {
    //num>50时,多个线程对50进行减1
    //int num=50;   继承Thread类实现多线程,每一次new创建实例都会 初始化实例变量num,
    // 最终运行是每一个线程的num初始为50
    //加入static修饰成为静态变量
    static int num = 50;

    @Override
    public void run() {
        while (true) {
            synchronized (Thread1.class) {
                if (num > 0) {
                    try {
                        //出现0,-1等情况,在num--前,多个线程进行了num判断
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //出现重复的num,情况与上例相似,在num--前,有多个线程进行了输出
                    System.out.println(getName() + ",num = " + num--);
                } else {
                    break;
                }
            }
        }
    }
}

最后

感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值