package cn.itcast.heima2;
/**
* 线程安全和同步
* @author asus
*
*/
public class TraditionalThreadSynchronized {
public static void main(String[] args) {
new TraditionalThreadSynchronized().init();
}
//创建这个方法是因为需要调用外部类所以声明了一个方法
//让两个线程同时执行一个output方法会出现的问题就是第一个线程还没执行完毕,第二个线程就已经进入output方法开始执行了
//解决方法:在output方法中添加一个关键字 synchronized
private void init(){
final Outputer outputer = new Outputer();
//创建一个线程执行下面创建的output方法
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("zhangxiaoxiang");
}
}
}).start();
//创建第二个线程执行下面创建的output方法
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output2("lihuoming");
}
}
}).start();
}
/**
* 这个类是再做把一个名字一个字一个字的输出到控制台
* 为了发现当两个线程同时运行时数显的问题
* @author asus
*
*/
static class Outputer{
public void output(String name){
int len = name.length();
//synchronized (name)方法包裹的代码,是为了解决多线程安全问题
//synchronized()这里面的参数是一个对象,而这个相当是一个门,一个对象进来了把钥匙带了进去
//另一个线程过来了,也就是另一个对象过来了没钥匙,是进不去的,所以需要等到第一个对象出来才能得到钥匙进去
//而互斥必须得是同一个对象, 所以我们在synchronized()方法中的参数使用this也就是当前对象
//synchronized()这个方法是保护的一小段代码,想保护这个方法中的所有代码怎么办呢?看下面方法
synchronized (this) {
for(int i = 0;i<len;i++){
//charAt(i)表示输出字符串的第几个字符
System.out.print(name.charAt(i));
}
System.out.println();
}
};
/**
* synchronized在一个方法中最好只出现一次,如果出现两次很可能出现死锁
* @param name
*/
public synchronized void output2(String name){
int len = name.length();
for(int i = 0;i<len;i++){
//charAt(i)表示输出字符串的第几个字符
System.out.print(name.charAt(i));
}
System.out.println();
};
/**
* 当我们在方法上加入static时,会发现output1和output3又不同步了,因为使用
* static时不会重新创建类,他使用的是class字节码格式,所以我们只需要在output1中的synchronized(this)方法中this参数改成当前类.class如Outputer.class
* synchronized(Outputer.class)
* @param name
*/
public static synchronized void output3(String name){
int len = name.length();
for(int i = 0;i<len;i++){
//charAt(i)表示输出字符串的第几个字符
System.out.print(name.charAt(i));
}
System.out.println();
};
}
}