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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

java多线程系列(1)

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

1,為什么需要線程?

作用:提升cpu的利用率,如,早期的dos系統(tǒng),執(zhí)行2個命令時( command 1, command 2 ),如果command1【假如是磁盤遍歷文件的IO操作】執(zhí)行的時間比較長,那么command 2必須等待,這種方式就是同步阻塞,

cpu就閑置了,為了提高cpu的利用率,我們就要使用多線程,如果一個任務(wù)時間比較長,cpu就暫時掛起他,去執(zhí)行另外的線程,所以線程一般是異步的。

2,每一個進(jìn)程至少會有一個線程在運(yùn)行

public class Test {public static void main(String[] args) {//打印線程的名稱 System.out.println( Thread.currentThread().getName() );}}

輸出結(jié)果為 "main" ,注意這個main是線程的名字,跟main函數(shù)的名字相同而已。

3,在java中實(shí)現(xiàn)多線程有2種方式

>繼承Thread類

>實(shí)現(xiàn)Runnable接口

在run方法中寫線程要執(zhí)行的任務(wù)

class MyThread extends Thread{public void run(){System.out.println( "MyThread::run" );} }public class ThreadUse1 {public static void main(String[] args) {MyThread mt = new MyThread();mt.start();System.out.println( "運(yùn)行結(jié)束" );}}

?

從運(yùn)行結(jié)果可知,run方法是在之后執(zhí)行的,雖然start開啟線程比? 【System.out.println( "運(yùn)行結(jié)束" );】 他早,這說明,CPU在調(diào)用線程的時候,是隨機(jī)的

4,再次驗證cpu調(diào)用線程的隨機(jī)性

class MyThreadRand extends Thread{public void run(){try{for ( int i = 0; i < 10; i++ ) {int time = ( int )( Math.random() * 1000 );Thread.sleep( time );System.out.println( "MyThread:" + Thread.currentThread().getName() );}}catch( InterruptedException e ){e.printStackTrace();}} }public class RandThread {public static void main(String[] args) {try{MyThreadRand mt = new MyThreadRand();mt.setName( "自定義線程" );mt.start();for ( int i = 0; i < 10; i++ ) {int time = ( int )( Math.random() * 1000 );Thread.sleep( time );System.out.println( "MainThread:" + Thread.currentThread().getName() );}}catch( InterruptedException e ){e.printStackTrace();}}}

從執(zhí)行結(jié)果可知,線程的調(diào)度沒有什么規(guī)律,是隨機(jī)的, 這里補(bǔ)充一點(diǎn),start方法作用是通知 “線程規(guī)劃器”,這個線程已經(jīng)準(zhǔn)備好了,等待調(diào)用線程的run方法,就是讓系統(tǒng)安排一個時間來調(diào)用run方法。如果直接調(diào)用run方法,線程就變成同步方式了,必須等待MyThreadRand的run方法執(zhí)行完成之后,才會執(zhí)行main函數(shù)中的線程

5,start方法的順序,不代表線程的啟動順序

class MyThreadStart extends Thread{private int i;public MyThreadStart( int i ) {this.i = i;}public void run(){System.out.println( i );} }public class RandThread2 {public static void main(String[] args) {MyThreadStart s1 = new MyThreadStart( 1 );MyThreadStart s2 = new MyThreadStart( 2 );MyThreadStart s3 = new MyThreadStart( 3 );MyThreadStart s4 = new MyThreadStart( 4 );MyThreadStart s5 = new MyThreadStart( 5 );MyThreadStart s6 = new MyThreadStart( 6 );MyThreadStart s7 = new MyThreadStart( 7 );MyThreadStart s8 = new MyThreadStart( 8 );MyThreadStart s9 = new MyThreadStart( 9 );MyThreadStart s10 = new MyThreadStart( 10 );s1.start();s2.start();s3.start();s4.start();s5.start();s6.start();s7.start();s8.start();s9.start();s10.start();}}

6,實(shí)現(xiàn)Runnable接口

class MyThreadRunnable implements Runnable {public void run(){System.out.println( Thread.currentThread().getName() );} }public class ThreadRunnable {public static void main(String[] args) {MyThreadRunnable mt = new MyThreadRunnable();Thread t = new Thread( mt );t.setName( "自定義線程1" );t.start();}}

?

那么兩種多線程的實(shí)現(xiàn)方式,有什么不同呢?

>繼承Thread類

>實(shí)現(xiàn)Runnable接口

1,使用繼承Thread類的方式,多線程之間的數(shù)據(jù)不共享

class MyThreadShare extends Thread{private int count = 5;public MyThreadShare( String name ){this.setName( name );}public void run(){while( count-- > 0 ){System.out.println( Thread.currentThread().getName() + "->" + count );}} }public class ThreadShare {public static void main(String[] args) { MyThreadShare mt1 = new MyThreadShare( "A" );MyThreadShare mt2 = new MyThreadShare( "B" );MyThreadShare mt3 = new MyThreadShare( "C" );mt1.start();mt2.start();mt3.start();} }

2,而要想實(shí)現(xiàn)線程之間的數(shù)據(jù)共享,我們可以改一下

備注:線程數(shù)據(jù)共享與不共享,都有對應(yīng)的場景,比如火車站4個窗口賣票,很顯然需要線程共享數(shù)據(jù)。如:總共用10張票,如果窗口賣了1張,其他窗口就指剩下9張,這才是比較貼近實(shí)際的,如果用第一種方式,相當(dāng)于有40張余票了。

class MyThreadShare2 extends Thread{private int count = 5; public void run(){while( count-- > 0 ){System.out.println( Thread.currentThread().getName() + "->" + count );}} }public class ThreadShare2 {public static void main(String[] args) { MyThreadShare2 mt = new MyThreadShare2();Thread ta = new Thread( mt, "A" );Thread tb = new Thread( mt, "B" );Thread tc = new Thread( mt, "C" );ta.start();tb.start();tc.start();} }

從結(jié)果上看,好像實(shí)現(xiàn)了,數(shù)據(jù)共享,但是有點(diǎn)異常,B->3 很明顯不對,這種現(xiàn)象,在多線程編程里面,叫“線程非安全”。現(xiàn)實(shí)生活中也有類似場景,比如4S店賣車,兩個客戶同時預(yù)訂了這輛車。那估計少不了一番辯論。怎么解決這個問題呢?一般來說,在客戶訂車之前,銷售員要先查看庫存,如果客戶下單,要把庫存占用。表明有人預(yù)訂,其他銷售員看見了,就知道車被預(yù)訂了。程序中也是類似。如果要訪問這個變量,我們就給他加鎖,類似于銷售員占用庫存。在方法前加上synchronized關(guān)鍵字。那么其他線程訪問的時候,必須拿到這把鎖,才能訪問。synchronized可以在任意對象或者方法上加鎖。

class MyThreadShare2 extends Thread{private int count = 5; // public void run(){ //產(chǎn)生線程非安全問題synchronized public void run(){while( count-- > 0 ){System.out.println( Thread.currentThread().getName() + "->" + count );}} }public class ThreadShare2 {public static void main(String[] args) { MyThreadShare2 mt = new MyThreadShare2();Thread ta = new Thread( mt, "A" );Thread tb = new Thread( mt, "B" );Thread tc = new Thread( mt, "C" );ta.start();tb.start();tc.start();} }

?3,模擬用戶登錄場景,如果有兩個用戶登錄,我們讓其中一個用戶線程占時掛起。看下會出現(xiàn)什么情況

class Login {private static String userName;private static String userPwd;public static void doPost( String _userName, String _userPwd ){try {userName = _userName;if( userName.equals( "ghostwu" ) ) {Thread.sleep( 3000 ); }userPwd = _userPwd;System.out.println( userName + "---->" + userPwd );}catch( InterruptedException e ){e.printStackTrace();}} }class ThreadA extends Thread{public void run(){Login.doPost( "ghostwu", "abc123" );} }class ThreadB extends Thread{public void run(){Login.doPost( "ghostwuB", "abc1234" );} }public class UserLogin {public static void main(String[] args) {ThreadA ta = new ThreadA();ThreadB tb = new ThreadB();ta.start();tb.start();}}

在A線程掛起的時候,他之前的賦值已經(jīng)被B線程改變了,所以結(jié)果與預(yù)想的ghostwu? abc123不同。很明顯,我們要上鎖。

synchronized public static void doPost( String _userName, String _userPwd ){try {userName = _userName;if( userName.equals( "ghostwu" ) ) {Thread.sleep( 3000 ); }userPwd = _userPwd;System.out.println( userName + "---->" + userPwd );}catch( InterruptedException e ){e.printStackTrace();}}

?

總結(jié)

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

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