多线程常见面试题

1、什么是线程?什么是多线程?

线程:轻量级进程,是操作系统进行调度的最小单位。
多线程:同时运行多个线程称为多线程。

2、多线程的实现有几种方法?区别是?为何要引入其他两个,用一个不行吗?

1>三种。(1)继承thread类,(2)实现runnable接口,(3)实现callable
2>继承thread类:优点:编码简单;缺点:继承了thread类,无法继承继承其他类,不利于扩展;

实现runnable接口:优点:线程任务类只是实现了Runnable接口,可以继续继承和实现。缺点:如果线程有执行结果是不能直接返回的。

实现callable接口:
优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强。
缺点:编程复杂

3>为了解决thread类不具有扩展性的缺点,但是后两种编码比较复杂。

3、什么是线程安全?如何解决线程安全?

1>线程安全:指的是多线程环境中,存在数据共享,一个线程访问的共享数据被其他线程修改了,就会出现线程安全问题。 在整个访问的过程中,无一共享的数据被其他线程修改,该线程就是安全的。程序运行过程中,使用了成员变量,且对成员变量数据进行了修改,就会存在数据共享问题,也就是线程安全问题。

2>如何解决线程安全问题:线程同步(核心思想加锁,同步代码块:synchronize)、

使用同步机制,使得在同一时间只能有一个线程修改共享数据,比如,同步代码块;

消除共享数据,即多个线程数据不共享或共享数据不被修改。

4、什么是线程池?临时线程什么时候创建?什么时候会开始拒绝任务?

1>线程池:可以复用线程的技术,提高线程的重复利用,减少资源浪费

2>新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程

3>核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝。

5.取钱案例

需求:小明和小红是一对夫妻,他们有一个共同的账户,余额是10万元,模拟2人同时去取钱10万。
分析:
①:需要提供一个账户类,创建一个账户对象代表2个人的共享账户。
②:需要定义一个线程类,线程类可以处理账户对象。
③:创建2个线程对象,传入同一个账户对象。
④:启动2个线程,去同-一个账户对象中取钱10万。
package com.lyzd.theadsafe;
//模拟取钱案例
public class ThreadDemo {
    public static void main(String[] args) {
//        1、定义线程类,创建一个共享的账户对象
     Account acc=new Account("1111",100000);
//2、创建两个线程对象,代表小明和小红同时进来
        new DrawThread(acc,"小红").start();
        new DrawThread(acc,"小明").start();
    }
}

package com.lyzd.theadsafe;

public class Account {
    private String cradid;
    private double money;
    public Account() {
    }
    public Account(String cradid, double money) {
        this.cradid = cradid;
        this.money = money;
    }
    /**
     小明,小红取钱
     */
    public void drawMoney(double money) {
//        1、谁来取钱,线程的名字就是人名
        String name=Thread.currentThread().getName();
        if (this.money>=money){
            System.out.println(name+"取钱成功,取走"+money);
            this.money-=money;
            System.out.println(name+"取钱后余额:"+this.money);
        }else {
            System.out.println(name+"来取钱,余额不足");
        }
    }
    public String getCradid() {
        return cradid;
    }
    public void setCradid(String cradid) {
        this.cradid = cradid;
    }
    public double getMoney() {
        return money;
    }
    public void setMoney(double money) {
        this.money = money;
    }
}
package com.lyzd.theadsafe;

/**
 取钱线程类
 */
public class DrawThread extends Thread{
//   接收处理的账户对象
    private Account acc;
    public DrawThread (Account acc,String name){
        super(name);
        this.acc=acc;
    }
    @Override
    public void run() {
//小明小红取钱
        acc.drawMoney(100000);
    }
}

如果按这个思路会出现线程安全问题,我们可以利用同步代码块,同步方法或lock为其上锁,从而实现线程安全
同步代码块:对Account类中的drawMoney方法上锁

    synchronized (this) {
            if (this.money>=money){
                System.out.println(name+"取钱成功,取走"+money);
                this.money-=money;
                System.out.println(name+"取钱后余额:"+this.money);
            }else {
                System.out.println(name+"来取钱,余额不足");
            }

同步方法:对Account类中的drawMoney方法上锁

  public synchronized void drawMoney(double money) {
        String name=Thread.currentThread().getName();
        if (this.money>=money){
            System.out.println(name+"取钱成功,取走"+money);
            this.money-=money;
            System.out.println(name+"取钱后余额:"+this.money);
        }else {
            System.out.println(name+"来取钱,余额不足");
        }
    }

lock:对Account类中的drawMoney方法上锁

        String name=Thread.currentThread().getName();
//加锁
        lock.lock();
        try {
            if (this.money>=money){
                System.out.println(name+"取钱成功,取走"+money);
                this.money-=money;
                System.out.println(name+"取钱后余额:"+this.money);
                System.out.println(10/0);
            }else {
                System.out.println(name+"来取钱,余额不足");
            }
        } finally {
            //解锁
            lock.unlock();
        }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值