JAVA多线程实现方式三及线程安全

多线程的实现方法三:利用Callable,FutureTask接口实现
* 1.得到任务对象
*    1.1定义类实现Callable接口,重写call方法(可以返回结果),封装要做的事
*    1.2用FutureTask把Callable对象封装成任务对象
* 2.把线程任务对象交给Thread处理
* 3.调用Thread的start方法启动线程,执行任务
* 4.线程执行完毕后,通过futureTask的get方法去获取任务执行的结果
*     方法名称                                 说明
*     publce FutureTask<>(Callable call)      把Callable对象封装成FutureTask对象
*     public v get()throws Exception          获取线程执行Call方法返回的结果
* 方式三优缺点:
* 优点:线程任务只是实现接口,可以继续继承类和实现接口,扩展性强
*      可以在线程执行完毕后去获取线程执行的结果
* 缺点:编码复杂一些
/*
* 目标:学会创建方式三:实现Callable接口,结合futureTask方法
* */
public class ThreadDemo3 {
    public static void main(String[] args) {
     //3.创建callable任务对象
        Callable<String> call=new MyCallable(100);
        //4.把callable任务对象封装成futureTask对象
        //futureTask作用:(futureTask属于runnable)可以交给thread
        //futureTask作用:可以在线程执行完毕以后通过调用其get方法得到线程执行的结果
        FutureTask<String> f1=new FutureTask<>(call);
        //5.交给线程处理
        Thread t1=new Thread(f1);
        t1.start();

        Callable<String> call2=new MyCallable(200);

        FutureTask<String> f2=new FutureTask<>(call2);

        Thread t2=new Thread(f2);
        t2.start();

        try {
            //如果f1.f2任务没有执行完毕,这里的代码会等待,直接线程跑完才会取结果
            String rs1=  f1.get();
            System.out.println("第一个结果:"+rs1);
            String rs2=  f2.get();
            System.out.println("第二个结果:"+rs2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
//1.定义一个任务类,实现Callable(因为要返回结果,所以是泛型),应该声明线程任务执行完毕后的数据类型
class MyCallable implements Callable<String> {
    private int n;

    public MyCallable(int n) {
        this.n = n;
    }

    //2.重写call方法(线程的任务方法)
    @Override
    public String call() throws Exception {
        int sum=0;
        for (int i = 1; i <=n ; i++) {
            sum+=i;
        }
        return "子线程执行的结果事:"+sum;
    }
}

----------------------------------------------------------------------------------------------

Thread常用方法,构造器
*       方法名称                             说明
* String getName()                          获取当前线程的名称,默认线程名称是Thread-索引
* void setName(String name)                 设置线程名称
* public static Thread currentThread()      返回对当前正在执行的线程对象的引用
* public static void sleep(long time)       让线程休眠指定的时间,单位为毫秒
* public void run()                         线程任务方法
* public void start()                       线程启动方法

--------------------------------------------------------------------------------------------------------------

线程安全问题:
*    多个线程同时操作同一个共享资源的时候可能会出现业务安全问题,成为线程安全问题
* 出现原因:
*    存在多线程并发;
*    同时访问共享资源;
*    存在修改共享资源;

案例:小明,小红同时在一个有10w元账户里取10w元

public class Account {
    private String carid;
    private double money;//账户余额

    public Account() {
    }

    public Account(String carid, double money) {
        this.carid = carid;
        this.money = money;
    }

    public String getCarid() {
        return carid;
    }

    public void setCarid(String carid) {
        this.carid = carid;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
//小明 小红
    public void drawMoney(double money) {
        //先获取谁来取钱,线程的命字就是人民
        String name=Thread.currentThread().getName();
        //1.判断账户是否有钱
        if(this.money>=100000){
            //2.取钱
            System.out.println(name+"来取钱,取出"+money);
            //3.更新余额
            this.money-=money;
            System.out.println(name+"取钱后,剩余"+this.money);
        }else {
            //4.余额不足
            System.out.println(name+"来取钱,余额不足");
        }
    }
}
public class ThreadSafe1 extends Thread{
    //接收处理账户对象
    private Account acc;
    public ThreadSafe1(Account acc,String name){
        super(name);
        this.acc=acc;
    }
    @Override
    public void run() {
        //小明,小红取钱
         acc.drawMoney(100000);
    }
}
/*
* 需求:模拟取钱案例(线程安全问题)
* */
public class ThreadSafe {
    public static void main(String[] args) {
        //1.定义一个线程类,创建一个共享的账户对象
        Account acc=new Account("卡号",100000);

        //2.创建2个线程对象,代表小明和小红同时进来
        new ThreadSafe1(acc,"小明").start();
        new ThreadSafe1(acc,"小红").start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值