关于多线程

1.多线程概述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.实现线程的两种方式

在这里插入图片描述

建议使用接口方式
在这里插入图片描述

1.实现线程方法一(继承Thread,重写run)

在这里插入图片描述

start()方法的作用是:启动一个分支线程,在JVM中开辟一个新的空间,这段代码任务完成之后,瞬间就结束了。此时线程就启动成功了。
在这里插入图片描述

在这里插入图片描述

2.run()和start()的区别

run()
在这里插入图片描述
start()
在这里插入图片描述
在这里插入图片描述

3.实现线程方法二(实现Runable接口)

在这里插入图片描述
采用匿名内部类方式
在这里插入图片描述

3.线程生命周期

在这里插入图片描述

4.获取线程的名字

在这里插入图片描述
在这里插入图片描述

5.获取当前线程对象

在这里插入图片描述
在这里插入图片描述

6.关于sleep()方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

sleep()实例

public class Main {
    public static void main(String[] args) throws IOException {
        MyRunable myRunable= new MyRunable();
        Thread t1=new Thread(myRunable);//实例化线程
        t1.setName("t1");
        t1.start();

        try {
            Thread.sleep(1000*7);//主线程 休眠 7秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"-->end");//主线程结束


    }




}
class MyRunable implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"--> begin");//线程开始
        try {
            Thread.sleep(1000*3);//休眠3秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        for (int i = 0; i < 100; i++) {
            System.out.println("分支线程-->"+i);

        }
        System.out.println(Thread.currentThread().getName()+"-->end");
    }
}

运行过程:在主线程创建线程 t1—> t1线程就绪 —>主线程开始休眠7秒–>主线程休眠的同时分支线程t1抢到时间片,运行线程t1—>t1先休息3秒再进行输出—>t1结束后,主线程还没有完成7秒休眠,将剩下的时间完成后,再开始继续主线程。

7.关于sleep()的面试题

在这里插入图片描述

答案:不可以
由源代码可知,sleep()是一个静态方法。作用是让当前 面线程休眠,出现在main方法中,所以 主线程休眠。(出现在哪个里 ,哪个休眠)在这里插入图片描述

8.sleep()方法与wait()方法的区别

这是一个常见的面试题,比较重要,也比较好理解。

1.相同点:

(1)这两个方法都能使线程进入阻塞状态

2.不同点:

(1)sleep()方法是Thread类中的静态方法;而wait()方法是Object类中的方法;

(2)sleep()方法可以在任何地方调用;而wait()方法只能在同步代码块或同步方法中使用(即使用synchronized关键字修饰的);

(3)这两个方法都在同步代码块或同步方法中使用时,sleep()方法不会释放同步监视器;而wait()方法则会释放同步监视器;

9.终止线程的休眠 .interrupt()

使用 .interrupt(); 这种终止休眠的方式已考虑java的异常处理机制

在这里插入图片描述

在这里插入图片描述

10.强行终止线程 .stop() (已过时)

在这里插入图片描述

11.合理终止线程的方式

在这里插入图片描述

在这里插入图片描述

在else中 进行数据存储,以防丢失
在这里插入图片描述

12.线程调度概述(了解)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

线程让位 .yield()

//线程让位
public class Main {
    public static void main(String[] args) throws IOException {
        MyRunable myRunable= new MyRunable();
        Thread t1=new Thread(myRunable);
        t1.setName("t1");
        t1.start();
        for (int i = 1; i<=1000; i++) {
            System.out.println(Thread.currentThread().getName()+"--->"+i);
     }
    }

}
class MyRunable implements Runnable{
    boolean run=true;
    @Override
    public void run() {
        for (int i = 1; i <=1000 ; i++) {
            if(i%100==0){
                Thread.yield();//当前线程暂停一下,让给主线程

            }
            System.out.println(Thread.currentThread().getName()+"--->"+i);

        }

    }

}

线程合并

在这里插入图片描述
在这里插入图片描述

13.关于多线程并发环境下,数据的安全问题

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

14. 两个线程对同一个账户的取款实例(线程安全)

出错实例

两个线程对同一账户进行取款 ,如果出现线程1取完款但还没有进行更新余额时(网络延迟),正好线程2也去取款这种情况。此时就会出现线程安全问题

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Account account=new Account(1,12000);
        MyThread t1=new MyThread(account);
        MyThread t2=new MyThread(account);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();


    }
}

public class Account {//账户类
    private  int number;//账号
    private float balance;//余额

    public Account() {
    }

    public Account(int number, float balance) {
        this.number = number;
        this.balance = balance;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public float getBalance() {
        return balance;
    }

    public void setBalance(float balance) {
        this.balance = balance;
    }


    //进行取款,并更新余额
    public void getMoney( float limit){
        float before=this.getBalance();
        float after=before-limit;
        try {
            Thread.sleep(500);//模拟网络延迟,导致还没更新余额,另一个线程就进来取款的方法,此时一定出错
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.setBalance(after);//更新余额

    }
}

public class MyThread extends Thread{//线程类
    private Account act;//账户对象
   public MyThread() {
   }
	public MyThread(Account act) {
        this.act = act;
    }

    public Account getAct() {
        return act;
    }

    public void setAct(Account act) {
        this.act = act;
    }

    @Override
    public void run() {
        //取款
        float limit=5000;//取款额
        act.getMoney(limit);//调用取款方法
        System.out.println(Thread.currentThread().getName()+"从账号"+ act.getNumber()+"取款"+limit+",账户余额"+act.getBalance());
        }
}

解决方法(采用线程同步机制)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

15.对synchronized的理解

在这里插入图片描述

同步代码块越小,效率约高

synchronized出现在实例方法上

在这里插入图片描述
在这里插入图片描述

synchronized三种写法

在这里插入图片描述

16.哪些变量有线程安全问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

17.synchronized面试题

1.

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.

因为synchronized 在实例方法上时,锁的this。在main中两个线程调用的同一个MyClass对象 mc ,所以当t2在执行doOther时,this被doSome锁住了 ,10秒后才会放锁,所以 需要等待。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.

在这里插入图片描述

在这里插入图片描述

4.


在这里插入图片描述

在这里插入图片描述

18.死锁现象概述

T1从上往下执行,先锁上面的对象。T2从下往上执行,当T1去锁下面的对象时,对象已经被T2锁住了,T2去锁上面的对象时,被T1占用。--------此时便是死锁的状态。
死锁会让程序停在那,不出异常也不出错误。

在这里插入图片描述

public class Test {
    public static void main(String[] args) {
        //创建两个对象,创建两个线程。分别对两对象进行访问,一个先访问o1,另一个先o2.

        Object o1 = new Object();
        Object o2=  new Object();
        MyTread t1= new MyTread(o1,o2);
        MyTread2 t2= new MyTread2(o1,o2);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();

    }
}




class MyTread extends Thread{
    Object o1;
    Object o2;

    public MyTread() {

    }

    public MyTread(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }

    @Override
    public void run() {
        synchronized (o1){
            try {
                Thread.sleep(1000);//锁住o1,进行休眠
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o2){

            }
        }


    }
}

class MyTread2 extends Thread{
    Object o1;
    Object o2;

    public MyTread2() {

    }

    public MyTread2(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }

    @Override
    public void run() {
        synchronized (o2){//先o2再o2
            try {
                Thread.sleep(1000);//锁住o2,进行休眠
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o1){

            }
        }


    }
}

19.开发中怎么解决线程安全问题

在这里插入图片描述

20.守护线程(后台线程)

1.概述

在这里插入图片描述

2.实现守护线程

在这里插入图片描述
在这里插入图片描述

21.定时器

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

22.实现线程的第三种方式(实现Callable接口)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

23.wait() 和 notify()

在这里插入图片描述

在这里插入图片描述

24.生产者和消费者模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Lock锁

在这里插入图片描述
在这里插入图片描述

与synchronized 与Lock的区别

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值