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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JAVA多线程学习(一)

發(fā)布時間:2025/3/13 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA多线程学习(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、什么是多線程?

很顯然,一隨便編敲一段簡單的小代碼,從main方法開始運行,計算機是一條一條地從上而下的串行執(zhí)行程序。那如果我們要同時執(zhí)行兩個任務(wù)呢?就比如你用瀏覽器上網(wǎng)看網(wǎng)頁的時候,你還能同時登QQ,還能同時下載電影……這些任務(wù)都是并行執(zhí)行的。在計算機的任務(wù)管理器里可以看到一個一個的正在運行的程序任務(wù),這些程序就是一個個一個的進程,而大多數(shù)進程下面都已多條線程同時執(zhí)行,所以,多線程其實就是多個任務(wù)在同時執(zhí)行。

雖然是多線程,但是CPU執(zhí)行命令仍然是一條一條執(zhí)行的。然而計算機CPU只有一個,雖然多核計算機能夠有虛擬多CPU的技術(shù)(這是我自己對多核CPU的理解,不夠準確請見諒),但是相對于計算機要實現(xiàn)的線程數(shù)量,簡直少的可憐。所以,當多線程在硬件實現(xiàn)的時候,CPU的處理方式是進行分時處理(TDMA時分多址有沒有!!?)。什么意思呢,就是在一段時間執(zhí)行這一條線程,一段時間執(zhí)行另外一條線程,所有的具有執(zhí)行資格的線程進行隨機的獲得CPU的執(zhí)行權(quán)。CPU的運算速度快的驚人,因此我們感覺上其實就是多線程在并發(fā)執(zhí)行了。

二、JAVA中多線程的使用,Thread類

“一切皆對象”在JAVA語言中是一個永恒不變的定理,自然線程這玩意同樣有個對象進行包裝。那就是Thread類。這個對象實現(xiàn)了一個Runnable接口,這個接口很簡單,就一個run方法。

對于要多線程執(zhí)行任務(wù),可以通過如下兩種方法來實現(xiàn)多線程:

1、繼承Thread類

通過將要實現(xiàn)的任務(wù)封裝成方法,再封裝成對象,然后繼承Thread類,將任務(wù)方法寫進run方法之中,在再父線程中用start方法啟動就可以了。比如如下開啟一個線程的代碼

package com.qyz.thread;public class ThreadDemo1 {public static void main(String[] args) {Thread t1 = new Demo("第一個線程");//start()開啟線程 t1.start();//輸出:第一個線程:被打開了 } } //繼承了Thread的對象 class Demo extends Thread{public Demo(String name){//父類構(gòu)造方法中可以給線程命名super(name);}//重寫run方法 @Overridepublic void run(){//打印線程名稱System.out.println(Thread.currentThread().getName() + ":被打開了");} }

?

?

2、通過實現(xiàn)Runnable接口

方法一的線程開啟方法有一個問題,就是當一個類的的繼承體系結(jié)構(gòu)之中,只有部分子類需要開啟新的線程執(zhí)行任務(wù),但由于是單繼承的,繼承了某個父類的子類不可能再繼承Thread方法,因此只有通過實現(xiàn)

Runnable方法來開啟線程。

1、某個類實現(xiàn)Runnable,并重寫run方法,封裝需要新開啟線程實現(xiàn)的任務(wù)。2、新建Thread(Runnable target,name)對象。將Runnable對象封裝進線程對象中。3、開啟線程start()

1 package com.qyz.thread; 2 3 public class ThreadDemo2 { 4 5 public static void main(String[] args) { 6 Thread t1 = new Thread(new Demo2(),"第二個線程"); 7 //start()開啟線程 8 t1.start(); 9 //輸出:第二個線程:被打開了 10 } 11 } 12 //實現(xiàn)了Runnable接口的對象 13 class Demo2 implements Runnable{ 14 //重寫run方法 15 @Override 16 public void run(){ 17 //打印線程名稱 18 System.out.println(Thread.currentThread().getName() + ":被打開了"); 19 } 20 }

?

三、多線程之間的同步問題

多線程好嗎?當然好,但是會有一個問題需要注意!那就是同步問題。在多個線程訪問同一對象數(shù)據(jù)時?有多條操作命令,本來想的是等一個線程操作完該對象后,另外一個線程再操作,但是由于CPU是隨機分時執(zhí)行線程,因此有可能當一個線程對共享對象操作到一半時,CPU就切向另外一個線程,導(dǎo)致出現(xiàn)意外的輸出結(jié)果。這樣的問題一半很難排查,因此需要在編寫代碼的時候多加注意!

沒有同步的買賣票事例

1 package com.qyz.thread; 2 3 public class TickerDemo1 { 4 public static void main(String[] args) { 5 SaleTicket st = new SaleTicket(); 6 //實現(xiàn)3個線程 7 Thread t1 = new Thread(st, "1號賣票員"); 8 Thread t2 = new Thread(st, "2號賣票員"); 9 Thread t3 = new Thread(st, "3號賣票員"); 10 //開啟線程 11 t1.start(); 12 t2.start(); 13 t3.start(); 14 } 15 } 16 class SaleTicket implements Runnable{ 17 //總共100張票 18 private int num = 100; 19 @Override 20 public void run() { 21 while(this.num > 0){ 22 //這個代碼太簡單,所以讓線程睡一會,突出同步問題 23 try {Thread.sleep(10);} catch (Exception e) {} 24 System.out.println(Thread.currentThread().getName() + "******" + num--); 25 } 26 } 27 }

?

本來不該出現(xiàn)的0號票出現(xiàn)了,意外情況

解決方法:加鎖

多線程中的鎖其實就像一扇門,一個線程進去之后,把門鎖上,另外一個線程就不能進來,直到門里面的線程執(zhí)行完畢出來。

JAVA中實現(xiàn)同步鎖通過關(guān)鍵字synchronized,有以下方法

1、同步代碼塊,需要同步的命令封裝進一個代碼塊中,加上一個對象做鎖即可

1 class SaleTicket implements Runnable{ 2 //總共100張票 3 private int num = 100; 4 //一個object對象充當鎖 5 private Object lock = new Object(); 6 @Override 7 public void run() { 8 while(true){ 9 //同步代碼塊封裝 10 synchronized (lock) { 11 if(this.num > 0){ 12 //這個代碼太簡單,所以讓線程睡一會,突出同步問題 13 try {Thread.sleep(10);} catch (Exception e) {} 14 System.out.println(Thread.currentThread().getName() + "******" + num--); 15 }else 16 break; 17 } 18 } 19 } 20 }

?

?

?輸出如下

問題解決!

2、同步函數(shù)

函數(shù)是一種封裝,代碼塊也是一種封裝,那能不能結(jié)合在一起呢?sure!那就是通過關(guān)鍵字將將方法變成同步函數(shù)。

1 class SaleTicket implements Runnable{ 2 //總共100張票 3 private int num = 100; 4 @Override 5 public void run() { 6 while(true){ 7 this.sale(); 8 } 9 } 10 //通過封裝成同步函數(shù)來實現(xiàn) 11 private synchronized void sale(){ 12 if(this.num > 0){ 13 //這個代碼太簡單,所以讓線程睡一會,突出同步問題 14 try {Thread.sleep(10);} catch (Exception e) {} 15 System.out.println(Thread.currentThread().getName() + "******" + num--); 16 } 17 } 18 }

?

成功解決!

轉(zhuǎn)載于:https://www.cnblogs.com/njupt-Qsimple/p/5618491.html

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的JAVA多线程学习(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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