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 hread>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 hread>
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 hread>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 hread>