第一個(gè)示例更多的是運(yùn)用了內(nèi)部類(lèi)的特性:
內(nèi)部類(lèi)重要特點(diǎn):可以訪(fǎng)問(wèn)外部的成員變量,所以?xún)?nèi)部類(lèi)不能在靜態(tài)方法中實(shí)例化。
因?yàn)殪o態(tài)方法運(yùn)行時(shí)不需要?jiǎng)?chuàng)建實(shí)例對(duì)象,而內(nèi)部類(lèi)想要訪(fǎng)問(wèn)成員變量,意味著外部類(lèi)肯定要?jiǎng)?chuàng)建實(shí)例對(duì)象,二者相互矛盾。
所以下面就會(huì)報(bào)錯(cuò)
public class Synchronized01 {
public static void main(String args[]) {
)
// final Outputer outputer=new Outputer(); //這樣做就沒(méi)有成員變量可以訪(fǎng)問(wèn)
// new Thread(new Runnable(){
//
// public void run() {
// while(true){
// try {
// Thread.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// outputer.outputer("zhangsan");
// }
// }}).start();
}
class Outputer {
void outputer(String name) {
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
但如果改成這樣就沒(méi)有問(wèn)題
public class Synchronized01 {
public static void main(String args[]) {
new Synchronized01().init();
}
// 此方法被調(diào)用時(shí)一定創(chuàng)建了外部類(lèi)對(duì)象
private void init() {
// 運(yùn)行時(shí)找外部類(lèi)對(duì)象,找調(diào)用init方法的對(duì)象
final Outputer outputer = new Outputer();
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.outputer("zhangsan");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.outputer("lisi");
}
}
}).start();
}
class Outputer {
void outputer(String name) {
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
運(yùn)行結(jié)果
lisi zhangsan lisi zhangsan lisi zhangsan lisi zhangsan lisi zhangsan
lisi zhangsan lisi zhangsan lisi zhanlgissain
zlhiasnig san lzihsain gsan zlhiasnig san zlhiasnig san zlhiasnig san
zlhiasnigsan zlhiasnig san lzihsain gsan lisi zhangsan lisi
解決方法
修改Ouputer
class Outputer {
public void outputer(String name) {
int len = name.length();
synchronized (this) {// 兩個(gè)線(xiàn)程用的是同一個(gè)outputer對(duì)象
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
// synchronized要在void之前
// 一個(gè)方法只能有一個(gè)synchronized,不然可能會(huì)造成死鎖
public synchronized void outputer2(String name) {
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
// class Outputer {
// String xxx = "";
//
// public void outputer(String name) {
// int len = name.length();
// xxx必須是同一個(gè)對(duì)象,如果是name就仍然會(huì)出錯(cuò) name是兩個(gè)對(duì)象
// synchronized (xxx) {
// for (int i = 0; i < len; i++) {
// System.out.print(name.charAt(i));
// }
// System.out.println();
// }
// }
//
// }
但如果每個(gè)run()中這樣寫(xiě)new Outputer()然后調(diào)用outputer(name)仍然會(huì)出錯(cuò),因?yàn)槊看蝞ew都是產(chǎn)生一個(gè)新的對(duì)象,而synchronized關(guān)鍵是針對(duì)同一個(gè)對(duì)象。
public class Synchronized02 {
public static void main(String[] args) {
new Synchronized02().init();
}
private void init() {
final Outputer outputer = new Outputer();
new Thread(new Runnable() {
public void run() { // 要執(zhí)行的操作
while (true) { // 循環(huán)操作
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.outputer("zhangsan");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.outputer("lisi");
//這樣仍然會(huì)出問(wèn)題 ----不是同一個(gè)對(duì)象。
// new Outputer().outputer("lisi"); }
}
}).start();
}
class Outputer {
public void outputer(String name) {
int len = name.length();
synchronized (this) {// 兩個(gè)線(xiàn)程用的是同一個(gè)outputer對(duì)象
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
// synchronized要在void之前
// 一個(gè)方法只能有一個(gè)synchronized,不然可能會(huì)造成死鎖
public synchronized void outputer2(String name) {
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
// class Outputer {
// String xxx = "";
//
// public void outputer(String name) {
// int len = name.length();
// xxx必須是同一個(gè)對(duì)象,如果是name就仍然會(huì)出錯(cuò) name是兩個(gè)對(duì)象
// synchronized (xxx) {
// for (int i = 0; i < len; i++) {
// System.out.print(name.charAt(i));
// }
// System.out.println();
// }
// }
//
// }
}
一個(gè)內(nèi)部類(lèi)前面加上static就變成了外部類(lèi)
靜態(tài)方法只能在外部類(lèi)中聲明
靜態(tài)方法只和字節(jié)碼對(duì)象有關(guān)
public class Synchronized03 {
public static void main(String[] args) {
new Synchronized03().init();
}
private void init() {
final Outputer outputer = new Outputer();
new Thread(new Runnable() {
public void run() { // 要執(zhí)行的操作
while (true) { // 循環(huán)操作
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.outputer("zhangsan");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.outputer2("lisi");
}
}
}).start();
}
static class Outputer { // 加上static 相當(dāng)于是個(gè)外部類(lèi)
public void outputer(String name) {
int len = name.length();
// 靜態(tài)方法不創(chuàng)建類(lèi)的實(shí)例對(duì)象,創(chuàng)建字節(jié)碼對(duì)象,靜態(tài)方法運(yùn)行時(shí)只和字節(jié)碼對(duì)象關(guān)聯(lián)
synchronized (Outputer.class) {
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
// synchronized要在void之前
// 靜態(tài)方法只能在外部類(lèi)中聲明
public static synchronized void outputer2(String name) {
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}