03-传统线程之间的互斥与通讯

当有多个线程同时访问同一个方法时,可能会出现线程不安全,银行转账的例子

下面是案例:

package cn.itcast.demo.thread;

public class TradictionalThreadSynchronized {
	public static void main(String[] args) {
		new TradictionalThreadSynchronized().init();
	}
	private void init() {	
		final Outputer outputer = new Outputer();		// 在静态方法内不能创建内部类对象
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.printStackTrace();
					}
					outputer.output("helloworld");		// 要调用匿名内部类方法,必须在变量前+final修饰
				}
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.printStackTrace();
					}
					outputer.output("zhangsan");		// 要调用匿名内部类方法,必须在变量前+final修饰
				}
			}
		}).start();
	}
	class Outputer {
		public void output(String name) {
			int len = name.length();
			for (int i=0; i<len; i++) {
				System.out.print(name.charAt(i));
			}
			System.out.println();
		}
	}
}

打印结果:

helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhangsan
helloworld
zhanghelloworld
san
zhangsan
helloworld
zhangsan
helloworld
zhangsan

解决方法:

package cn.itcast.demo.thread;

public class TradictionalThreadSynchronized {
	public static void main(String[] args) {
		new TradictionalThreadSynchronized().init();
	}
	private void init() {	
		final Outputer outputer = new Outputer();		// 在静态方法内不能创建内部类对象
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.printStackTrace();
					}
					outputer.output("helloworld");		// 要调用匿名内部类方法,必须在变量前+final修饰
				}
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.printStackTrace();
					}
					outputer.output("zhangsan");		// 要调用匿名内部类方法,必须在变量前+final修饰
				}
			}
		}).start();
	}
	class Outputer {
		String obj = "";		// 2. 定义一个对象,synchronized参数必须是同一个对象才能实现线程同步
		public void output(String name) {
			int len = name.length();
			synchronized (obj) {		// 1.加关键字,线程同步,当一个线程正在执行这段代码,其他线程就不能使用
				for (int i=0; i<len; i++) {
					System.out.print(name.charAt(i));
				}
				System.out.println();
			}
		}
	}
}

更加好的方法:this

              synchronized (this) {			// +this关键字,表示当前对象,指的是outputer对象
				for (int i=0; i<len; i++) {
					System.out.print(name.charAt(i));
				}
				System.out.println();
			}

保护整个方法,并且同一个对象调用不同方法,也是没有问题的

package cn.itcast.demo.thread;

public class TradictionalThreadSynchronized {
	public static void main(String[] args) {
		new TradictionalThreadSynchronized().init();
	}
	private void init() {	
		final Outputer outputer = new Outputer();		// 在静态方法内不能创建内部类对象
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.printStackTrace();
					}
					outputer.output("helloworld");		// 要调用匿名内部类方法,必须在变量前+final修饰
				}
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.printStackTrace();
					}
					outputer.output2("zhangsan");		// 要调用匿名内部类方法,必须在变量前+final修饰
				}
			}
		}).start();
	}
	class Outputer {
		public void output(String name) {
			int len = name.length();
			synchronized (this) {			// +this关键字,表示当前对象,指的是outputer对象
				for (int i=0; i<len; i++) {
					System.out.print(name.charAt(i));
				}
				System.out.println();
			}
		}
		// 保护整个方法
		public synchronized void output2(String name) {
			int len = name.length();
			synchronized (this) {			
				for (int i=0; i<len; i++) {
					System.out.print(name.charAt(i));
				}
				System.out.println();
			}
		}
	}
}

下面代码会出现线程不同步

package cn.itcast.demo.thread;

public class TradictionalThreadSynchronized {
	public static void main(String[] args) {
		new TradictionalThreadSynchronized().init();
	}
	private void init() {	
		final Outputer outputer = new Outputer();		// 在静态方法内不能创建内部类对象
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.printStackTrace();
					}
					outputer.output("helloworld");		// 要调用匿名内部类方法,必须在变量前+final修饰
				}
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.printStackTrace();
					}
					outputer.output3("zhangsan");		// 要调用匿名内部类方法,必须在变量前+final修饰
				}
			}
		}).start();
	}
	static class Outputer {
		public void output(String name) {
			int len = name.length();
			synchronized (this) {			// +this关键字,表示当前对象,指的是outputer对象
				for (int i=0; i<len; i++) {
					System.out.print(name.charAt(i));
				}
				System.out.println();
			}
		}
		public static synchronized void output3(String name) {
			int len = name.length();
			for (int i=0; i<len; i++) {
				System.out.print(name.charAt(i));
			}
			System.out.println();
		}
	}
}

解决方法:

package cn.itcast.demo.thread;

public class TradictionalThreadSynchronized {
	public static void main(String[] args) {
		new TradictionalThreadSynchronized().init();
	}
	private void init() {	
		final Outputer outputer = new Outputer();		// 在静态方法内不能创建内部类对象
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.printStackTrace();
					}
					outputer.output("helloworld");		// 要调用匿名内部类方法,必须在变量前+final修饰
				}
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.printStackTrace();
					}
					outputer.output3("zhangsan");		// 要调用匿名内部类方法,必须在变量前+final修饰
				}
			}
		}).start();
	}
	static class Outputer {
		public void output(String name) {
			int len = name.length();
			synchronized (Outputer.class) {		// synchronized的参数一定是同一个对象才能互斥,否则不能互斥	
				for (int i=0; i<len; i++) {
					System.out.print(name.charAt(i));
				}
				System.out.println();
			}
		}
		public static synchronized void output3(String name) {
			int len = name.length();
			for (int i=0; i<len; i++) {
				System.out.print(name.charAt(i));
			}
			System.out.println();
		}
	}
}

 

posted @ 2017-08-15 22:34  半生戎马,共话桑麻、  阅读(120)  评论(0)    收藏  举报
levels of contents