开启两个线程,分别打印两种字符串,字符串按一个一个的字母输出.如果不加锁,则会出现打印一半字符串时,CPU分配时间片到另一个线程上打印,造成打印一半的现象.如下测试:
/**
* synchronized关键字
*/
public class SyncTest {
public static void main(String[] args) {
SyncTest syncTest = new SyncTest();
syncTest.init();
}
private void init() {
final Outputer outputer = new Outputer();
//创建两个线程,分别输入不同的字符串
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.out1("meiran");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.out2("zhoutong");
}
}
}).start();
}
class Outputer {
/**
* 对调用的对象加锁(因为调用的对象为同一对象)
*
* @param name
*/
public void out1(String name) {
int length = name.length();
synchronized (this) {
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println("");
}
}
/**
* 对方法加锁(对调用此方法的对象加锁)
*
* @param name
*/
public synchronized void out2(String name) {
int length = name.length();
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println("");
}
}
}
以上代码需要说明的问题:
1、对象加锁,使用this关键字的意思是:对调用该方法的对象加锁。
2、方法上加synchronized与使用this关键字等价。
3、内部匿名类中使用局部变量,局部变量需为final的。4、static方法访问非static的内部类,因非static的内部类可以访问外部类的成员变量,说明非static的内部类的对象需由外部类的对象调用,所以需加非static的内部类的对象放入非static的内部类的方法中,由static方法调用非static的方法实现。
5、static方法调非static方法需要创建对象。
测试用例2:
/**
* 理解static方法的锁对象是谁
*/
public class SyncTest2 {
public static void main(String[] args) {
SyncTest2 syncTest = new SyncTest2();
syncTest.init();
}
private void init() {
final Outputer outputer = new Outputer();
//创建两个线程,分别输入不同的字符串
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.out1("meiran");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.out2("zhoutong");
}
}
}).start();
}
static class Outputer {
/**
* 对字节码类对象加锁
*
* @param name
*/
public void out1(String name) {
int length = name.length();
synchronized (Outputer.class) {
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println("");
}
}
/**
* 静态方法加锁是对字节码类对象加锁
*
* @param name
*/
public static synchronized void out2(String name) {
int length = name.length();
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println("");
}
}
}
以上代码需要说明的问题:
1、static方法的锁对象是字节码文件的对象。
2、内部类不能有static方法。必须定义为静态内部类,相当于顶级类。