日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

启动多线程的两种情况比较

發(fā)布時(shí)間:2024/8/24 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 启动多线程的两种情况比较 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

啟動(dòng)多線程有兩種方式:(都是在主線程main線程下)

1. 使用同一個(gè)線程對(duì)象來(lái)啟多個(gè)線程

2. 使用多個(gè)線程對(duì)象來(lái)啟多個(gè)線程

?

這兩種方式有什么區(qū)別呢?先貼上代碼舉例說(shuō)明:

這是使用線程對(duì)象MyRunnable的同一個(gè)實(shí)例r來(lái)啟動(dòng)了兩個(gè)線程

MyRunnable r = new MyRunnable(); Thread ta = new Thread(r,"Thread-A"); Thread tb = new Thread(r,"Thread-B"); ta.start(); tb.start();

?

這是使用線程對(duì)象MyRunnable的兩個(gè)不同的實(shí)例r來(lái)啟動(dòng)了兩個(gè)線程

MyRunnable r1 = new MyRunnable(); MyRunnable r2 = new MyRunnable();Thread ta = new Thread(r1,"Thread-A"); Thread tb = new Thread(r2,"Thread-B"); ta.start(); tb.start();

?

那么使用這兩種方式的區(qū)別在哪里呢?我們緊接著看下面的代碼的運(yùn)行結(jié)果:

public class MyRunnable implements Runnable {private Foo foo =new Foo(); public static void main(String[] args) {MyRunnable r = new MyRunnable();Thread ta = new Thread(r,"Thread-A"); Thread tb = new Thread(r,"Thread-B"); ta.start(); tb.start(); /*MyRunnable r1 = new MyRunnable();MyRunnable r2 = new MyRunnable();Thread ta = new Thread(r1,"Thread-A"); Thread tb = new Thread(r2,"Thread-B"); ta.start(); tb.start();*/} public void run() {for (int i = 0; i < 3; i++) {this.fix(30);try {Thread.sleep(1); } catch (InterruptedException e) {e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " :當(dāng)前foo對(duì)象的x值= " + foo.getX());} } public int fix(int y) {return foo.fix(y);} }class Foo {private int x = 100;public int getX() {return x;} public int fix(int y) {x = x - y; return x;} }

?

使用同一個(gè)線程對(duì)象啟多個(gè)線程的運(yùn)行結(jié)果:

Thread-B :當(dāng)前foo對(duì)象的x值= 40
Thread-B :當(dāng)前foo對(duì)象的x值= 10
Thread-A :當(dāng)前foo對(duì)象的x值= -20
Thread-B :當(dāng)前foo對(duì)象的x值= -50
Thread-A :當(dāng)前foo對(duì)象的x值= -50
Thread-A :當(dāng)前foo對(duì)象的x值= -80

?

使用多個(gè)線程對(duì)象啟動(dòng)多個(gè)線程的運(yùn)行結(jié)果:

Thread-A :當(dāng)前foo對(duì)象的x值= 70
Thread-B :當(dāng)前foo對(duì)象的x值= 70
Thread-B :當(dāng)前foo對(duì)象的x值= 40
Thread-A :當(dāng)前foo對(duì)象的x值= 40
Thread-A :當(dāng)前foo對(duì)象的x值= 10
Thread-B :當(dāng)前foo對(duì)象的x值= 10

?

我們可以看到在改變值的過(guò)程中,值串了。并且線程執(zhí)行也是串的,兩個(gè)線程之間在相互爭(zhēng)搶執(zhí)行。
(線程ta的run方法還沒(méi)有執(zhí)行完,tb的run方法爭(zhēng)搶到了cpu資源從而執(zhí)行)

在改變值的過(guò)程中,值改變是對(duì)的。線程執(zhí)行是串的。(值沒(méi)有串,是因?yàn)閒oo是私有變量,屬于ta,tb所各自私有)

?

是我們不能允許的,因?yàn)橹荡恕?br />都出現(xiàn)的線程之間相互爭(zhēng)搶的問(wèn)題,就看我們的業(yè)務(wù)實(shí)現(xiàn)了。
使用多線程時(shí),我們有時(shí)就是想啟用多個(gè)線程同時(shí)去干不同的事情,這時(shí)它們相互爭(zhēng)搶執(zhí)行就是我們想要的。
有時(shí),在多個(gè)線程同時(shí)訪問(wèn)一個(gè)方法時(shí),我們希望當(dāng)一個(gè)線程執(zhí)行完這個(gè)方法后,再讓其他的線程去執(zhí)行,這時(shí),我們就要避免線程之間相互爭(zhēng)搶的問(wèn)題,也就是使用同步鎖機(jī)制來(lái)控制。

?

好,如果我們現(xiàn)在想要run()方法執(zhí)行完了之后,其他線程才能再次進(jìn)入run()方法來(lái)執(zhí)行。我們用同步關(guān)鍵字synchronized來(lái)實(shí)現(xiàn)。如下:

同步方法:

synchronized public void run() {for (int i = 0; i < 3; i++) {this.fix(30);try {Thread.sleep(1); } catch (InterruptedException e) {e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " :當(dāng)前foo對(duì)象的x值= " + foo.getX());} }

同步塊:

public void run() {synchronized(this){for (int i = 0; i < 3; i++) {this.fix(30);try {Thread.sleep(1); } catch (InterruptedException e) {e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " :當(dāng)前foo對(duì)象的x值= " + foo.getX());} }}

?

對(duì)于我們使用上面的同步方法和同步塊都能得到如下的輸出:

Thread-A :當(dāng)前foo對(duì)象的x值= 70
Thread-A :當(dāng)前foo對(duì)象的x值= 40
Thread-A :當(dāng)前foo對(duì)象的x值= 10
Thread-B :當(dāng)前foo對(duì)象的x值= -20
Thread-B :當(dāng)前foo對(duì)象的x值= -50
Thread-B :當(dāng)前foo對(duì)象的x值= -80

?

對(duì)于我們使用上面的同步方法和同步塊卻得到如下的輸出:

Thread-A :當(dāng)前foo對(duì)象的x值= 70
Thread-B :當(dāng)前foo對(duì)象的x值= 70
Thread-A :當(dāng)前foo對(duì)象的x值= 40
Thread-B :當(dāng)前foo對(duì)象的x值= 40
Thread-A :當(dāng)前foo對(duì)象的x值= 10
Thread-B :當(dāng)前foo對(duì)象的x值= 10

?

的結(jié)果與我們預(yù)期的是一樣的,但是卻不如我們的預(yù)期,各個(gè)線程之間還是在相互爭(zhēng)搶執(zhí)行。

為什么呢?我們不是都已經(jīng)使用synchronized同步了嗎?

導(dǎo)致這個(gè)問(wèn)題的根源就是對(duì)象鎖的問(wèn)題。

中使用同步方法時(shí),線程ta,tb對(duì)應(yīng)的對(duì)象鎖都為MyRunnable的實(shí)例對(duì)象r,對(duì)象鎖共享且唯一,所以起到了同步的作用。
同理,使用同步塊時(shí),ta,tb的對(duì)象鎖也都是MyRunnable的實(shí)例對(duì)象r,故也能達(dá)到效果。

但對(duì)于不同的是,使用方法同步和塊同步時(shí),線程ta,tb對(duì)應(yīng)的對(duì)象鎖分別是各自的線程對(duì)象的實(shí)例,即ta-->r1,tb-->r2。故線程ta,tb分別持有各自的對(duì)象鎖,所以達(dá)不到同步的效果。

?

如果換成如下代碼執(zhí)行

public void run() {synchronized("123"){for (int i = 0; i < 3; i++) {this.fix(30);try {Thread.sleep(1); } catch (InterruptedException e) {e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " :當(dāng)前foo對(duì)象的x值= " + foo.getX());} }}

我們得到如下結(jié)果:

Thread-A :當(dāng)前foo對(duì)象的x值= 70
Thread-A :當(dāng)前foo對(duì)象的x值= 40
Thread-A :當(dāng)前foo對(duì)象的x值= 10
Thread-B :當(dāng)前foo對(duì)象的x值= 70
Thread-B :當(dāng)前foo對(duì)象的x值= 40
Thread-B :當(dāng)前foo對(duì)象的x值= 10

?

這下就和我們的預(yù)期一樣了。ta,tb線程都持有字符串"123"作為對(duì)象鎖,ta,tb線程中的"123"都指向相同的內(nèi)存地址,故對(duì)象鎖相同且共享,故能達(dá)到同步效果。(為什么ta,tb中的"123"指向相同的內(nèi)存地址,與String對(duì)象本身比較特殊有關(guān),在此不贅述)

對(duì)于文章中的對(duì)象鎖問(wèn)題有疑問(wèn)的,可以參見(jiàn)另一篇博文:http://www.cnblogs.com/kevin-yuan/archive/2013/04/27/3047511.html

轉(zhuǎn)載于:https://www.cnblogs.com/kevin-yuan/p/4111242.html

與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的启动多线程的两种情况比较的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。