线程的互斥和协作

public class Synchronized{
    static class Account{
        private double money = 1000.0d;
        
        //异步存钱
        public void noSynDesposit(double fFees){
            System.out.println("Account noSynDesposit begin! money = "+ this.money + "; fFees = "+fFees);
            System.out.println("noSynDesposit sleep begin");
            try{
                Thread.sleep(3000);
            }catch(InterruptedException e){
                e.printStackTrace();
                }
            System.out.println("noSynDesposit end");
            this.money = this.money + fFees;
            System.out.println("Account noSynDesposit end! money = "+ this.money);
            }
            
        //异步取钱
        public void noSynWithdraw(double fFees){
            System.out.println("Account noSynWithdraw begin! money = "+ this.money + "; fFees = "+fFees);
            System.out.println("noSynWithdraw sleep begin");
            try{
                Thread.sleep(3000);
            }catch(InterruptedException e){
                e.printStackTrace();
                }
            System.out.println("noSynWithdraw sleep end");
            this.money = this.money - fFees;
            System.out.println("Account noSynWithdraw end! money = "+ this.money);
            }
            
        //同步存钱
        public synchronized void synDesposit(double fFees){
            System.out.println("Account synDesposit begin! money = "+ this.money + "; fFees = "+fFees);
            System.out.println("synDesposit sleep begin");
            try{
                Thread.sleep(3000);
            }catch(InterruptedException e){
                e.printStackTrace();
                }
            System.out.println("synDesposit end");
            this.money = this.money + fFees;
            System.out.println("Account synDesposit end! money = "+ this.money);
            }    
            
        //同步取钱
        public synchronized void synWithdraw(double fFees){
            System.out.println("Account synWithdraw begin! money = "+ this.money + "; fFees = "+fFees);
            System.out.println("synWithdraw sleep begin");
            try{
                Thread.sleep(3000);
            }catch(InterruptedException e){
                e.printStackTrace();
                }
            System.out.println("synWithdraw sleep end");
            this.money = this.money - fFees;
            System.out.println("Account synWithdraw end! money = "+ this.money);
            }
        }
        
    static class AccessThread extends Thread{
        private Account account = null;
        private String method = "";
        public AccessThread(Account account, String method){
            this.account = account;
            this.method = method;
            }
            
        public void run(){
            if(method.equals("noSynDesposit")){
                account.noSynDesposit(500.0);
            }else if(method.equals("noSynWithdraw")){
                account.noSynWithdraw(200.0);
            }else if(method.equals("synDesposit")){
                account.synDesposit(500.0);
            }else if(method.equals("synWithdraw")){
                account.synWithdraw(200.0);
                }
        }
    }
        
    public static void main(String[] args){
        //线程的运行具有不确定性,与启动顺序无关,取决于JVM,所以异步就可能出现
        Account account = new Account();
        //同一个账户多个线程调用不同的方法,修改同一个变量值
        System.out.println("account 1 :"+account.toString());
        Thread threadA = new AccessThread(account, "noSynDesposit");
        Thread threadB = new AccessThread(account, "noSynWithdraw");
        threadA.start();
        threadB.start();
        
        try{
            //waits for this thread to die
            threadA.join();
            threadB.join();
        }catch(InterruptedException e){
            e.printStackTrace();
            }
        
        System.out.println();
        account = new Account();
        System.out.println("account 2 :"+account.toString());
        Thread threadC= new AccessThread(account, "synDesposit");
        Thread threadD = new AccessThread(account, "synWithdraw");
        threadC.start();
        threadD.start();
        }
    }
G:\maul keyboard\thread>java Synchronized
account 1 :Synchronized$Account@153bcbc8
Account noSynDesposit begin! money = 1000.0; fFees = 500.0
Account noSynWithdraw begin! money = 1000.0; fFees = 200.0
noSynWithdraw sleep begin
noSynDesposit sleep begin
noSynWithdraw sleep end
Account noSynWithdraw end! money = 800.0
noSynDesposit end
Account noSynDesposit end! money = 1300.0

account 2 :Synchronized$Account@1b61d282
Account synDesposit begin! money = 1000.0; fFees = 500.0
synDesposit sleep begin
synDesposit end
Account synDesposit end! money = 1500.0
Account synWithdraw begin! money = 1500.0; fFees = 200.0
synWithdraw sleep begin
synWithdraw sleep end
Account synWithdraw end! money = 1300.0

G:\maul keyboard\thread>

 

import java.util.Vector;


public class WaitNotify{
    static class Printer extends Thread{
        /**
        1.start、run、addTask、stopPrinter因为要协同作用,所以都没有使用synchronized同步,所以他们的运行没有先后顺序
        2.通过其他方法(addTask、stopPrinter)来修改线程占用对象的资源,并控制线程的运行(run方法)
        3.addTask、stopPrinter方法中的synchronized代码块,同一时刻仅允许一个线程进入,控制同一变量因不同方法修改而不一致
        4.线程处于等待状态仅仅是线程暂停运行run方法了,线程还可以运行属于它的其他方法,通过其他方法唤醒线程,继续运行run方法
        5.在线程协同场景下,线程一般结合synchronized代码块使用
        */
        Vector task = new Vector();
        private boolean running = false;
        public void start(){
            running = true;
            super.start();
            }
        public void run(){
            try{
                System.out.println("printer begin");
                while(running){
                    System.out.println("task.isEmpty :"+task.isEmpty()+" running : "+running);
                    //同步代码块,同一时间只允许一个线程访问该对象,避免task属性不一致
                    synchronized (this){
                        while(task.isEmpty() && running){
                            System.out.println("wait begin");
                            //线程等待,释放所占对象所有资源
                            this.wait();
                            System.out.println("wait end");
                            }
                        }
                if(running){
                    //不断打印队列首个消息,打印时一并移出
                    System.out.println("print the task : "+task.remove(0));
                    }
                }
                System.out.println("printer end");
            }catch(InterruptedException e){
                e.printStackTrace();
                }
        
            }
        //使用线程释放的资源,修改资源后,再唤醒线程继续执行
        @SuppressWarnings("unchecked")    
        public void addTask(String str){
            synchronized (this){
                this.task.add(str);
                System.out.println("task size : "+task.size());
                this.notify();
//                this.notifyAll();
                }
            }
            
        public void stopPrinter(){
            synchronized (this){
                this.running = false;
                System.out.println("stopPrinter notify");
                this.notify();
                }
            }
        }
    
    public static void main(String[] args){
        //线程和线程操作的对象是同一个
        Printer printer = new Printer();
        printer.start();
        System.out.println("==========================================================");
        try{
            //留出休眠时间等待线程把符合条件的语句执行完
            Thread.sleep(200);
            for(int i=0;i<3;i++){
                //1.留出休眠时间等待线程被唤醒,再生成任务
                //2.留出休眠时间等待任务生成
                Thread.sleep(200);
                printer.addTask("The task "+i);
            }
        }catch(InterruptedException e){
            e.printStackTrace();
            }
            
        try{
            //留出休眠时间等待线程执行完,如果不休眠等待,则可能所有的任务不能都执行完
            Thread.sleep(200);
            printer.stopPrinter();
        }catch(InterruptedException e){
            e.printStackTrace();
            }
        }
    }
G:\maul keyboard\thread>java WaitNotify
==========================================================
printer begin
task.isEmpty :true running : true
wait begin
task size : 1
wait end
print the task : The task 0
task.isEmpty :true running : true
wait begin
task size : 1
wait end
print the task : The task 1
task.isEmpty :true running : true
wait begin
task size : 1
wait end
print the task : The task 2
task.isEmpty :true running : true
wait begin
stopPrinter notify
wait end
printer end

G:\maul keyboard\thread>

 

posted @ 2018-08-11 20:01  celineluo  阅读(244)  评论(0编辑  收藏  举报