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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

《Java 高并发》05 线程的基本操作

發(fā)布時(shí)間:2023/12/10 java 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Java 高并发》05 线程的基本操作 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

volatile 與 Java 內(nèi)存模型

Java 內(nèi)存模型都是圍繞著原子性、有序性和可見性展開的。為了在適當(dāng)?shù)膱龊?#xff0c;確保線程間的原子性、有序性和可見性。Java 使用了一些特許的操作或者關(guān)鍵字來申明、告訴虛擬機(jī),在這個(gè)地方,要尤其注意,不能隨意變動(dòng)優(yōu)化目標(biāo)指令。volatile 關(guān)鍵字就是其中之一。

當(dāng)用 volatile 去申明一個(gè)變量是,就等于告訴虛擬機(jī),這個(gè)變量極有可能會(huì)被某些程序或者線程修改。為了確保這個(gè)變量被修改后,應(yīng)用程序范圍內(nèi)的所有線程都能“看到”這個(gè)改動(dòng),虛擬機(jī)就必須采用一些特殊的手段,保證這個(gè)變量的可見性等特點(diǎn)。

特別注意,volatile 并不能代替鎖,它也無法保證一些符合操作的原子性。

使用示例:

public class MultiThreadLong {private static Long to = 0L;public static class ChangI implements Runnable {private Long to;public ChangI(Long to) {this.to = to;}@Overridepublic void run() {while (true) {MultiThreadLong.to = this.to;Thread.yield();}}}public static class ReadI implements Runnable {@Overridepublic void run() {while (true) {Long to = MultiThreadLong.to;if (to != 111 && to != -999 && to != 333 && to != 444) {System.out.println(to);Thread.yield();}}}}public static void main(String[] args) {new Thread(new ChangI(111L)).start();new Thread(new ChangI(-999L)).start();new Thread(new ChangI(333L)).start();new Thread(new ChangI(444L)).start();new Thread(new ReadI()).start();new Thread().stop();}}

線程組

在一個(gè)系統(tǒng)中,如果線程數(shù)量過多,而且功能分配比較明確,就可以將相同功能的線程放置在一個(gè)線程組中。

public class ThreadGroupName implements Runnable{@Overridepublic void run() {String groupAndName = Thread.currentThread().getThreadGroup().getName() +"-"+Thread.currentThread().getName();while (true){System.out.println("I am " + groupAndName);try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {ThreadGroup groupName1 = new ThreadGroup("groupName1");Thread thread1 = new Thread(groupName1,new ThreadGroupName(),"t1");Thread thread2 = new Thread(groupName1,new ThreadGroupName(),"t2");thread1.start();thread2.start();ThreadGroup groupName2 = new ThreadGroup("groupName2");Thread thread3 = new Thread(groupName2,new ThreadGroupName(),"t3");Thread thread4 = new Thread(groupName2,new ThreadGroupName(),"t4");thread3.start();thread4.start();} }

上述創(chuàng)建了兩個(gè)線程組 groupName1、groupName2,并創(chuàng)建了四個(gè)線程命名為 t1、t2、t3、t4,分別將 t1、t2 放入 groupName1中,t3、t4 放入 groupName2 中。日志打印如下:

I am groupName1-t1 I am groupName2-t4 I am groupName2-t3 I am groupName1-t2

注意:ThreadGroup 提供 stop() 方法,它會(huì)停止線程組內(nèi)的所有線程。但它會(huì)出現(xiàn)和 Thread.stop() 相同的問題。

守護(hù)線程

守護(hù)線程是一種特殊的線程,就和它的名字一樣,它是系統(tǒng)的守護(hù)者,在后臺(tái)默默地完成一些系統(tǒng)性的服務(wù),比如垃圾回收線程。與之相對(duì)應(yīng)的是用戶線程,用戶線程可以認(rèn)為是系統(tǒng)的工作線程,它會(huì)完成這個(gè)程序應(yīng)該要完成的業(yè)務(wù)操作。 如果用戶線程全部結(jié)束,這也就意味著這個(gè)程序?qū)嶋H上無事可做了。守護(hù)線程要收的對(duì)象已經(jīng)不存在了,那么整個(gè)應(yīng)用程序就自然應(yīng)該結(jié)束。因此,當(dāng)一個(gè) Java 應(yīng)用內(nèi),只有守護(hù)線程時(shí),Java 虛擬機(jī)就會(huì)自然退出。

想要?jiǎng)?chuàng)建一個(gè)守護(hù)線程只需要將它設(shè)置為守護(hù)線程即可,具體實(shí)現(xiàn):

public class DaemonThread {public static class DaemonT implements Runnable{@Overridepublic void run() {while (true){System.out.println(System.currentTimeMillis() + "I am alive.");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {try {DaemonT daemonT = new DaemonT();Thread thread = new Thread(daemonT);// 設(shè)置為守護(hù)線程thread.setDaemon(true);thread.start();Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}} }

線程優(yōu)先級(jí)

Java 中的線程有自己的優(yōu)先級(jí)。優(yōu)先級(jí)高的線程在競爭資源師會(huì)更有有事,更可能搶占資源,當(dāng)然,這個(gè)是一個(gè)概率問題。高優(yōu)先級(jí)線程也有可能搶占失敗。

在 Java 中,使用 1 到 10 表示線程優(yōu)先級(jí),數(shù)字越大優(yōu)先級(jí)越高,默認(rèn)優(yōu)先級(jí)為 5。可以使用內(nèi)置的三個(gè)靜態(tài)變量來表示優(yōu)先級(jí):

public final static int MIN_PRIORITY = 1;public final static int NORM_PRIORITY = 5;public final static int MAX_PRIORITY = 10;

線程優(yōu)先級(jí)的使用:

public class PriorityDemo {public static class HightPriority extends Thread {static int count = 0;@Overridepublic void run() {while (true) {synchronized (HightPriority.class) {count++;if (count > 10000000){System.out.println("HightPriority is complate");break;}}}}}public static class LowPriority extends Thread {static int count = 0;@Overridepublic void run() {while (true) {synchronized (HightPriority.class) {count++;if (count > 10000000){System.out.println("LowPriority is complate");break;}}}}}public static void main(String[] args) {HightPriority hightPriority = new HightPriority();LowPriority lowPriority = new LowPriority();hightPriority.setPriority(Thread.MAX_PRIORITY);lowPriority.setPriority(Thread.MIN_PRIORITY);lowPriority.start();hightPriority.start();}}

上述代碼創(chuàng)建了兩個(gè)線程,分別是 HightPriority 設(shè)置為高優(yōu)先級(jí)、LowPriority 設(shè)置為低優(yōu)先級(jí)。讓他們完成相同的工作,對(duì) count 累加到 10000000,通過打印結(jié)果知道誰先完成工作。在對(duì) count 累加前,使用 synchronized 產(chǎn)生一次資源競爭。目的是是的優(yōu)先級(jí)的差異表現(xiàn)更為明顯。

public class PriorityDemo {public static class HightPriority extends Thread {static int count = 0;@Overridepublic void run() {while (true) {synchronized (HightPriority.class) {count++;if (count > 10000000){System.out.println(System.currentTimeMillis() + " HightPriority is complate");break;}}}}}public static class LowPriority extends Thread {static int count = 0;@Overridepublic void run() {while (true) {synchronized (HightPriority.class) {count++;if (count > 10000000){System.out.println(System.currentTimeMillis() + " LowPriority is complate");break;}}}}}public static void main(String[] args) {HightPriority hightPriority = new HightPriority();LowPriority lowPriority = new LowPriority();hightPriority.setPriority(Thread.MAX_PRIORITY);lowPriority.setPriority(Thread.MIN_PRIORITY);lowPriority.start();hightPriority.start();} }

synchronized

synchronized 的作用是實(shí)現(xiàn)線程間的同步。它的工作是對(duì)同步的代碼加鎖,是的每一次只能有一個(gè)線程進(jìn)入同步塊,從而保證線程間的安全性。

關(guān)鍵字 synchronized 使用方法:

  • 同步代碼塊:同步代碼塊可以指定加鎖對(duì)象,進(jìn)入同步代碼錢獲得給定對(duì)象的鎖。
  • 作用于普通方法:相當(dāng)于給當(dāng)前實(shí)例加鎖,進(jìn)入同步代碼前要獲得當(dāng)前實(shí)例的鎖。
  • 作用于靜態(tài)方法:相當(dāng)于對(duì)當(dāng)前類加鎖,進(jìn)入同步代碼錢要獲得當(dāng)前類的鎖。
  • 釋放方式一:同步代碼塊

    public class AccountingSync implements Runnable {static AccountingSync instance = new AccountingSync();static int num = 0;@Overridepublic void run() {for (int j = 0; j < 100000000; j++) {synchronized (instance) {num++;}}}public static void main(String[] args) {try {Thread t1 = new Thread(instance, "thread1");Thread t2 = new Thread(instance, "thread2");t1.start();t2.start();t1.join();t2.join();System.out.println(num);} catch (InterruptedException e) {e.printStackTrace();}}}

    使用方式二:同步方法

    public class AccountingSync2 implements Runnable {static AccountingSync2 instance = new AccountingSync2();static int num = 0;public synchronized void increase() {num++;}@Overridepublic void run() {for (int j = 0; j < 100000000; j++) {increase();}}public static void main(String[] args) {try {Thread t1 = new Thread(instance, "thread1");Thread t2 = new Thread(instance, "thread2");t1.start();t2.start();t1.join();t2.join();System.out.println(num);} catch (InterruptedException e) {e.printStackTrace();}} }

    基于上面兩種凡是的錯(cuò)誤加鎖實(shí)現(xiàn):

    public class AccountingSync2 implements Runnable {static AccountingSync2 instance = new AccountingSync2();static int num = 0;public synchronized void increase() {num++;}@Overridepublic void run() {for (int j = 0; j < 100000000; j++) {increase();}}public static void main(String[] args) {try {Thread t1 = new Thread(new AccountingSync2(), "thread1");Thread t2 = new Thread(new AccountingSync2(), "thread2");t1.start();t2.start();t1.join();t2.join();System.out.println(num);} catch (InterruptedException e) {e.printStackTrace();}}}

    上述鎖對(duì)象是當(dāng)前調(diào)用實(shí)例對(duì)象,但是在創(chuàng)建兩個(gè)線程時(shí)都指向了不同的 AccountingSync2 鎖對(duì)象。因此線程 t1 在進(jìn)入同步方法前加鎖 自己的 AccountingSunc2 實(shí)例,而線程 t2 也加鎖自己 AccountingSync2 實(shí)例鎖。因此,線程安全是無法保證的。

    為解決上述請(qǐng),synchronized 的第三種使用方式,將其作用在靜態(tài)方法上。

    public class AccountingSync3 implements Runnable {static AccountingSync3 instance = new AccountingSync3();static int num = 0;public synchronized static void increase() {num++;}@Overridepublic void run() {for (int j = 0; j < 100000000; j++) {increase();}}public static void main(String[] args) {try {Thread t1 = new Thread(new AccountingSync3(), "thread1");Thread t2 = new Thread(new AccountingSync3(), "thread2");t1.start();t2.start();t1.join();t2.join();System.out.println(num);} catch (InterruptedException e) {e.printStackTrace();}}}

    靜態(tài)同步方法的鎖對(duì)象是當(dāng)前類.class,盡管上訴兩個(gè)線程創(chuàng)建了兩個(gè)實(shí)例對(duì)象,但是他們使用的鎖是同一個(gè)。

    總結(jié)

    以上是生活随笔為你收集整理的《Java 高并发》05 线程的基本操作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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