Java多线程学习三

线程安全

1.同步代码块
线程安全:《Java 并发实践》多个线程,访问一个类的对象,如果不考虑这些线程在运行环境下的调度和交替执行,并且不需要额外同步和调用方法,也不需要额外的代码块的协调,那么这个类仍是正确的。那么这个类就是线程安全的类。

实例:

public class SafeThread{
	public static void main(String[] args) {
		new SafeThread().safeThreadTest();
	}
	
	PrintString ps = new PrintString();
	public void safeThreadTest() {
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true) {
					ps.showString("AAAAAAAAAAAAA");
				}				
			}
		}).start();
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true) {
					ps.showString("BBBBBBBBBBBB");
				}			
			}
		}).start();
	}
}

class PrintString{
	//synchronized是一把锁,一次只允许一个线程进入方法体内
	public synchronized void showString(String str) {
		for(int i=0;i<str.length();i++) {
			System.out.print(str.charAt(i));
		}
		System.out.println();
	} 
}
class PrintString{
	public void showString(String str) {
		//第二种方式:锁住要执行的代码
		//锁住类的字节码PrintString.class或者this当前对象或str.getclass()
		synchronized(this) {
			for(int i=0;i<str.length();i++) {
				System.out.print(str.charAt(i));
			}
			System.out.println();
		}
	} 
}

同步代码块:就是定义了一组原子性的操作,所谓原子性的操作,就是说只允许一个线程进入。直到这个线程运行完毕,下一个线程才能进入。

下面我们来看另一个实例:
同时开启两个线程,每个线程自加到10000,两个线程求和。(应该为两万)

public class SafeThread2 {
	public int i=0;
	AddTest at = new AddTest();
	
	public static void main(String[] args) {
		new SafeThread2().threadTest();
	}
	//线程二自加一万
	public void threadTest() {
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0;i<10000;i++) {
					at.add();
				}
			}
		}).start();
		//线程二自加一万
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0;i<10000;i++) {
					at.add();
				}
				
			}
		}).start();
		//等待上方线程结束
		//如果上方两个线程没有执行结束,会一直阻塞
		//得到当前线程活跃的数量:新建线程一线程二,主线程
		while(Thread.activeCount()!=1) {
		}
		System.out.println(i);
	}
	
	class AddTest{
		public synchronized void add() {
			i++;
		}
	}
}

下面还有一个ATM取钱的实例:

public class ATM extends Thread{
	
	private String name;
	private int money;
	private Account account;
	
	public ATM(String name, int money, Account account) {
		super();
		this.name = name;
		this.money = money;
		this.account = account;
	}
	
	@Override
	public void run() {
		synchronized (account) {
			if(money<account.getBalance()) {
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				//设置账户的余额
				account.setBalance(account.getBalance()-money);
				//检测账户的余额
				System.out.println("账户的余额为:"+account.getBalance());
			}else {
				System.out.println("账户余额不足...");
			}
		}
		
	}
	
	public static void main(String[] args) {
		Account a=new Account("888888",6000);
		new ATM("张三", 5000, a).start();
		new ATM("李四", 5000, a).start();
	}
	
}

你可能感兴趣的:(JAVA笔记,Java,多线程)