今天看啥  ›  专栏  ›  独饮敌敌畏丶_4109

Java学习27 2020-03-13

独饮敌敌畏丶_4109  · 简书  ·  · 2020-03-13 16:08

内容

1.线程中的两个不常用方法介绍
2.线程同步机制初步

一.线程中的两个不常用方法介绍

1.Thread.yield()

Thread.yield()与sleep()类似,只是 不能由用户指定暂停多长时间 ,并且yield()方法只能让 同优先级 的线程有执行的机会, 让位时间不固定
注意:该方法也是一个 静态方法

2.t.join()

t.join()是 线程合并 ,合并之后就可能变成了 单线程 的程序。
这一行代码出现在哪个线程中,t就和哪个线程合并。从这也可以看出, join()是成员方法

二.线程同步机制初步

1.先了解两个概念

①异步编程模型:t1线程执行t1的,t2线程执行t2的,两个线程之间 谁也不等谁 (一般情况下效率更高)
②同步编程模型:t1线程和t2线程执行,但 t1线程必须等t2线程执行结束之后,t1线程才能执行 ,这就是同步编程模型(也就是接下来要讲的)

2.为何要引入线程同步?

为了 数据的安全 。尽管应用程序的使用效率降低了。
线程同步机制使程序变成了(等同)单线程。

3.什么条件下使用线程同步?

①必须是多线程环境
②多线程环境 共享同一个数据
③共享的数据 涉及修改操作 (比如只涉及查找操作,那就不需要线程同步)

4.错误示范

以下程序不使用线程同步机制, 多线程同时对同一个账户进行取款操作 ,看看会出现什么问题


public class 测试程序   {                                                                                                             
                                                                                                                        
    public static void main(String[] args) throws InterruptedException  {
   
        //创建一个公共的账户
        Account act = new Account("actno",5000.0);
        
        //创建两个线程,这两个线程对同一个账户取款
        Thread t1 = new Thread(new Processor(act));
        Thread t2 = new Thread(new Processor(act));
   
        //开始取款
        t1.start();
        t2.start();
                
    }

   
    
}

//取款线程
class Processor implements Runnable{
    
    //账户
    Account act;
    
    //构造方法
    Processor(Account act){
        this.act = act;
    }
    
    public void run() {
        act.withdraw(1000);
        System.out.println("取款1000元成功,余额为:" + act.getBalance());
    }
}
//账户
class Account{
    
    private String actno;
    private double balance;
    
    //构造方法
    public Account(String actno,double balance) {
        this.actno = actno;
        this.balance = balance;
    }
    
    //setter and getter
    public void setBalance(double balance) {
        this.balance = balance;
    }
    
    public double getBalance() {
        return balance;
    }
    
    //对外提供一个取款的方法
    public void withdraw(double money) {
        double after = balance - money;
        
        //更新余额
        this.setBalance(after);
    }
}


输出结果

取款1000元成功,余额为:4000.0
取款1000元成功,余额为:4000.0

这就已经不对了,取出来2000.0,应该还剩3000.0
所以我们对于类似这种情况,就要使用线程同步了

5.线程同步的语法

synchronized(共享对象){}
{}里面放需要同步的代码

6.以下程序使用线程同步机制

public class 测试程序   {                                                                                                             
                                                                                                                        
    public static void main(String[] args) throws InterruptedException  {
   
        //创建一个公共的账户
        Account act = new Account("actno",5000.0);
        
        //创建两个线程,这两个线程对同一个账户取款
        Thread t1 = new Thread(new Processor(act));
        Thread t2 = new Thread(new Processor(act));
   
        //开始取款
        t1.start();
        t2.start();
                
    }

   
    
}

//取款线程
class Processor implements Runnable{
    
    //账户
    Account act;
    
    //构造方法
    Processor(Account act){
        this.act = act;
    }
    
    public void run() {
        act.withdraw(1000);
        System.out.println("取款1000元成功,余额为:" + act.getBalance());
    }
}
//账户
class Account{
    
    private String actno;
    private double balance;
    
    //构造方法
    public Account(String actno,double balance) {
        this.actno = actno;
        this.balance = balance;
    }
    
    //setter and getter
    public void setBalance(double balance) {
        this.balance = balance;
    }
    
    public double getBalance() {
        return balance;
    }
    
    //对外提供一个取款的方法
    public void withdraw(double money) {
        
        synchronized(this) {
            double after = balance - money;
            
            //延迟
            try{Thread.sleep(1000);}catch(Exception e) {}
            
            //更新余额
            this.setBalance(after); 
        }
        
    }
}


输出结果

取款1000元成功,余额为:4000.0
取款1000元成功,余额为:3000.0

而且是每1s输出一行
这样就是我们需要的,虽然效率降低了,但是安全是最重要的




原文地址:访问原文地址
快照地址: 访问文章快照