第二十八(线程的同步、守护线程、Timer 定时器)

/*
    模拟ATM取款,不是线程同步机制,多线程同时对一个账户进行操作

    t1 和 t2
    
        异步编程模型:t1线程执行t1,t2线程执行的是t2,两个线程之间谁也不等于谁
        
        同步编程模型:t1线程和t2线程执行,当t1线程必须等于t2的线程执行结果之后,t1线程才能执行
                          这是同步编程模型。
        
        什么时候需要引入同步
            
            1. 为了数据安全,尽管应用程序的使用率低,但是为了保证数据安全性,必须的加入线程同步机制
            
            线程同步机制 使程序变成了(等同)单线程
            
            2. 在什么条件下需要使用线程同步
                <1> 必须是多线程环境
                <2> 多线程环境在共享同一个数据时
                <3> 共享的数据涉及到修改操作 

*/
public class ThreadTest01{
    
    public static void main(String[] args){
        
        // 创建一个公共账户
        Account act = new Account("Ming",10000.0);
        
        // 创建线程对同一个账户进行取款
        Thread t1 = new Thread(new Ming01(act));
        Thread t2 = new Thread(new Ming01(act));
        
        t1.start();
        t2.start();
        
    }

}

// 取款的线程
class Ming01 implements Runnable{
    
    // Account 账户
    Account act;
    
    Ming01(Account act){
        this.act = act;
    }
    
    public void run(){
        act.withdraw(2000.0);
        System.out.println("取款2000.0¥成功,余额为:" + act.getBalance());
    }
    

}


// 银行账户
class Account{
    
    private String actno;
    private double balance; // 账户余额
    
    public Account(){}
    
    public Account(String actno,double balance){
        this.actno = actno;
        this.balance = balance;
    }
    
    public void setActno(String actno){
        this.actno = actno;    
    }
    public String getActno(){
        return actno;    
    }

    public void setBalance(double balance){
        this.balance = balance;    
    }
    public double getBalance(){
        return balance;    
    }
    
    
    
    // 对外提供一个取款方法
    public void withdraw(double money){
        
        // 对账户进行取款操作
        double after = balance - money;
        
        // 延迟
        try{
            Thread.sleep(1000);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        
        // 更新账号余额
        this.setBalance(after);
    }
}
//输出取款2000.0¥成功,余额为:8000.0
/*
    以下程序使用线程同步机制保证数据安全型

*/
public class ThreadTest02{
    
    public static void main(String[] args){
        
        // 创建一个公共账户
        Account act = new Account("ming",10000.0);
        
        // 创建线程对同一个账户进行取款
        Thread t1 = new Thread(new Ming01(act));
        Thread t2 = new Thread(new Ming01(act));
        
        t1.start();
        t2.start();
        
    }

}

// 取款的线程
class Ming01 implements Runnable{
    
    // Account 账户
    Account act;
    
    Ming01(Account act){
        this.act = act;
    }
    
    public void run(){
        act.withdraw(2000.0);
        System.out.println("取款2000.0¥成功,余额为:" + act.getBalance());
    }
    

}


// 银行账户
class Account{
    
    private String actno;
    private double balance; // 账户余额
    
    public Account(){}
    
    public Account(String actno,double balance){
        this.actno = actno;
        this.balance = balance;
    }
    
    public void setActno(String actno){
        this.actno = actno;    
    }
    public String getActno(){
        return actno;    
    }

    public void setBalance(double balance){
        this.balance = balance;    
    }
    public double getBalance(){
        return balance;    
    }
    
    
    
    // 对外提供一个取款方法
    public void withdraw(double money){
        
        
        /*
            需要把同步的代码,放到同步的语句块中
            
            t1线程执行到此处,遇到了 synchronized关键字,就会去找this的对象锁
            如果找到了this的对象锁,则进入同步语句块 执行程序。
            当同步语句块代码执行结束的时候,t1线程归还this的对象锁
            
            在t1线程执行同步语句块的过程中,如果t2线程也过来执行以下代码,遇到synchronized关键字
            所以也去找this对象锁,但是该对象被t1线程持有
            只能在等待this对象的归还
        */

        synchronized(this){

            // 对账户进行取款操作
            double after = balance - money;
            
            // 延迟
            try{
                Thread.sleep(2000);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            
            // 更新账号余额
            this.setBalance(after);
        }
    }
    
}

 

/*
    以下程序使用线程同步机制保证数据安全型

*/
public class ThreadTest03{
    
    public static void main(String[] args){
        
        // 创建一个公共账户
        Account act = new Account("ming",10000.0);
        
        // 创建线程对同一个账户进行取款
        Thread t1 = new Thread(new Ming01(act));
        Thread t2 = new Thread(new Ming01(act));
        
        t1.start();
        t2.start();
        
    }

}

// 取款的线程
class Ming01 implements Runnable{
    
    // Account 账户
    Account act;
    
    Ming01(Account act){
        this.act = act;
    }
    
    public void run(){
        act.withdraw(2000.0);
        System.out.println("取款2000.0¥成功,余额为:" + act.getBalance());
    }
    

}


// 银行账户
class Account{
    
    private String actno;
    private double balance; // 账户余额
    
    public Account(){}
    
    public Account(String actno,double balance){
        this.actno = actno;
        this.balance = balance;
    }
    
    public void setActno(String actno){
        this.actno = actno;    
    }
    public String getActno(){
        return actno;    
    }

    public void setBalance(double balance){
        this.balance = balance;    
    }
    public double getBalance(){
        return balance;    
    }
    
    
    
    // 对外提供一个取款方法
    // synchronized关键字 添加到成员方法上,线程拿走的也是this对象锁
    public synchronized void withdraw(double money){
        
        
        /*
            需要把同步的代码,放到同步的语句块中
            
            t1线程执行到此处,遇到了 synchronized关键字,就会去找this的对象锁
            如果找到了this的对象锁,则进入同步语句块 执行程序。
            当同步语句块代码执行结束的时候,t1线程归还this的对象锁
            
            在t1线程执行同步语句块的过程中,如果t2线程也过来执行以下代码,遇到synchronized关键字
            所以也去找this对象锁,但是该对象被t1线程持有
            只能在等待this对象的归还
        */

        //synchronized(this){

            // 对账户进行取款操作
            double after = balance - money;
            
            // 延迟
            try{
                Thread.sleep(2000);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            
            // 更新账号余额
            this.setBalance(after);
        //}
    }
    
}
/*
    定义一个用户线程
    
*/
public class UserThread01{
    
    public static void main(String[] args){
        
        Runnable r1 = new UserTest();
        Thread t1 = new Thread(r1,"t1");
        
        t1.start();
        
        for(int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName() + " : " + i);    
        }
        
        System.out.println("主线程结束 !");
        
    }

}

class UserTest implements Runnable{
    
    public void run(){
        for(int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName() + " : " + i);
        }
    }

}


/////////////////////////////////////////////////////////////////////////



/*
    守护线程
    
         其他所有的用户线程结束,则守护线程退出
         守护线程一般都是无限执行的
    
    设置了守护线程以后,当前主线程结束后,守护线程并没有把所有的数据输出就结束
    也就是说 守护线程是为 用户线程服务的,当用户线程全部结束,守护线程会自动结束
    
    跟我们的 java中自动垃圾回收机制GC 是一个原理
    
*/
public class UserThread02{
    
    public static void main(String[] args){
        
        Thread t1 = new UserTest();
        t1.setName("t1");
        
        // 将t1这个用户线程 修改成守护线程
        t1.setDaemon(true);
        
        t1.start();
        
        // 主线程
        
        for(int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName() + " : " + i);    
            try{
                Thread.sleep(1000);
            } catch(InterruptedException e){}
        }        
        System.out.println("主线程结束 !");
    
    }

}

class UserTest extends Thread{
    
    public void run(){
        int i = 0;
        while(true){
            i ++;
            System.out.println(Thread.currentThread().getName() +"  : "+i);
            try{
                Thread.sleep(1000);
            } catch(InterruptedException e){
                
            }
        }    
    }

}
/*
    Timer定时器

*/

import java.util.*;
import java.text.*;

public class TimerTest{
    
    public static void main(String[] args){
        Timer t = new Timer();
        try{
        
            Date d = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2015-1-20 23:35:30");
            // 安排在指定的时间执行指定的任务
            // t.schedule(new MyTimer(),d,1000*60*60*24); 24小时执行一次
             t.schedule(new MyTimer(),d,1000*2);
        
        } catch(NullPointerException e){
            e.printStackTrace();
        } catch(IllegalArgumentException e){
            e.printStackTrace();    
        } catch(IllegalStateException e){
            e.printStackTrace();        
        } catch(ParseException e){
            e.printStackTrace();    
        }
    }

}


class MyTimer extends TimerTask{
    
    public void run(){
        System.out.println(new Date());    
    }

}

 

posted @ 2015-01-19 23:10  哥的笑百度不到  阅读(350)  评论(0编辑  收藏  举报