Java学习27 2020-03-13

内容

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输出一行
这样就是我们需要的,虽然效率降低了,但是安全是最重要的

你可能感兴趣的:(Java学习27 2020-03-13)