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>