国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

ホームページ Java &#&ベース Java 同時(shí)プログラミングとスレッド セーフの基本の概要

Java 同時(shí)プログラミングとスレッド セーフの基本の概要

Feb 24, 2021 am 10:10 AM
java スレッドの安全性

Java 同時(shí)プログラミングとスレッド セーフの基本の概要

無料學(xué)習(xí)の推奨事項(xiàng): Java 基本チュートリアル

スレッド セーフティの基本

    ##1. スレッド セーフティの問題
  • ##2. アカウント引き出しケース
  • ##3. 同期されたコード ブロックの同期
  • synchronized についての理解
    • java の 3 つの主要な変數(shù)のスレッド安全性の問題
    • インスタンス メソッドでの synchronized の使用
    • 概要
    • インタビュー質(zhì)問
    • 4. デッドロック
  • 5. 開発中のスレッド セーフティの問題を解決する方法
  • 6. デーモン スレッド
  • 7.タイマー
  • 8. スレッドを?qū)g裝する 3 番目の方法: Callable インターフェイスを?qū)g裝します
  • 9. オブジェクト クラスの wait メソッドと notification メソッド
  • 10.Producer と Consumer
  • 1. スレッドの安全性の問題

2.1. これが重要な理由は何ですか? 將來の開発では、プロジェクトはすべてサーバー上で実行され、サーバーはスレッドの定義、スレッド オブジェクトの作成、スレッドの起動(dòng)をすでに実裝しています。このコードを記述する必要はありません。

最も重要なことは、作成したプログラムはマルチスレッド環(huán)境で実行する必要があることを知っておく必要があることです。より注意を払う必要があるのは、データがマルチスレッドの同時(shí)実行環(huán)境で安全であるかどうかです。環(huán)境。 (強(qiáng)調(diào): *****)

2.2. マルチスレッド同時(shí)環(huán)境でデータにセキュリティ上の問題が発生するのはどのような場(chǎng)合ですか?



3 つの條件: Java 同時(shí)プログラミングとスレッド セーフの基本の概要 條件 1: マルチスレッドの同時(shí)実行。
條件2:共有データがある。 條件3:共有データが変更されている。

## 上記の 3 つの條件が満たされると、スレッドの安全性の問題が発生します。
2.3. スレッドの安全性の問題を解決するにはどうすればよいですか?
マルチスレッドの同時(shí)環(huán)境に共有データがあり、このデータが変更される場(chǎng)合、スレッド セーフティの問題が発生します。この問題を解決するにはどうすればよいですか? スレッドは実行のためにキューに入れられます。 (同時(shí)にはできません)。


スレッドの安全性の問題を解決するには、キュー実行を使用します。 この仕組みをスレッド同期機(jī)構(gòu)といいます。
専門用語(yǔ)は次のとおりです。 スレッド同期。これは、実際にはスレッドを同時(shí)に実行することができず、実行のためにスレッドをキューに入れる必要があることを意味します
。

スレッド セーフティの問題を解決するにはどうすればよいですか? 「スレッド同期メカニズム」を使用します。
スレッドの同期とは、スレッドをキューに入れることを意味します。スレッドがキューに入れられると、効率の一部が犠牲になります。方法はありません。データのセキュリティが優(yōu)先されます。データが安全である場(chǎng)合にのみ、効率について話すことができます。データは安全ではなく、効率もありません。 2.4. スレッドの同期に関しては、次の 2 つの専門用語(yǔ)が関係します:
非同期プログラミング モデル:

スレッド t1 とスレッド t2 はそれぞれ獨(dú)自の t1 を?qū)g行します。 t2 は気にしない、t2 は t1 を気にしない、誰(shuí)も誰(shuí)かを待つ必要がない このプログラミング モデルは非同期プログラミング モデルと呼ばれます。
実際には、次のとおりです: マルチスレッドの同時(shí)実行 (効率が高くなります。)
同期プログラミング モデル:

スレッド t1 とスレッド t2 が実行されます。スレッド t1 の場(chǎng)合、t2 スレッドの実行が終了するまで待機(jī)する必要があります。つまり、t2 スレッドが実行中に、t1 スレッドの実行が終了するまで待機(jī)する必要があります。両者の間には待機(jī)関係が発生します。スレッド これは同期プログラミング モデルです。効率が低い。スレッドは実行のためにキューに入れられます。

非同期とは同時(shí)実行を意味します。同期はキューイング中です。

2. アカウント引き出しケース

アカウント クラス

package?ThreadSafe;public?class?Account?{
	//賬號(hào)
	private?String?actno;
	//余額
	private?double?balance;
	
	public?Account(String?actno,?double?balance)?{
		super();
		this.actno?=?actno;
		this.balance?=?balance;
	}
	public?String?getActno()?{
		return?actno;
	}
	public?void?setActno(String?actno)?{
		this.actno?=?actno;
	}
	public?double?getBalance()?{
		return?balance;
	}
	public?void?setBalance(double?balance)?{
		this.balance?=?balance;
	}
	//取款的方法
	public?void?withdraw(double?money){
		//t1和t2并發(fā)執(zhí)行這個(gè)方法(t1和t2是兩個(gè)棧?,兩個(gè)棧操作堆中同一個(gè)對(duì)象)
		//取款之前的余額
		double?before=this.getBalance();
		//取款之后的余額
		double?after=before-money;
		//模擬一下網(wǎng)絡(luò)延遲,會(huì)出現(xiàn)問題
		try?{
			Thread.sleep(1000);
		}?catch?(InterruptedException?e)?{
			//?TODO?Auto-generated?catch?block
			e.printStackTrace();
		}
		//更新余額
		//思考:t1執(zhí)行到這里了,但還沒有來得及執(zhí)行這行代碼,t2線程進(jìn)來withdraw方法了,此時(shí)一定出問題
		this.setBalance(after);
	}}AccountThread類public?class?AccountThread?extends?Thread{
	//兩個(gè)線程必須共享一個(gè)賬戶對(duì)象
	private?Account?act;
	//通過構(gòu)造方法傳遞過來賬戶對(duì)象
	public?AccountThread(Account?act)?{
		this.act?=?act;
	}
	@Override
	public?void?run()?{
		//假設(shè)取款5000
		double?money=5000;
		//多線程執(zhí)行這個(gè)方法
		act.withdraw(money);
		System.out.println(Thread.currentThread().getName()+"賬戶"+act.getActno()+"取款成功"+act.getBalance());
	}}

テスト クラス

public?class?Test?{
	public?static?void?main(String[]?args)?{
		//創(chuàng)建賬戶對(duì)象
		Account?act=new?Account("act-001",10000);
		//創(chuàng)建兩個(gè)線程
		Thread?t1=new?AccountThread(act);
		Thread?t2=new?AccountThread(act);
		
		t1.setName("t1");
		t2.setName("t2");
		//啟動(dòng)兩個(gè)線程執(zhí)行
		t1.start();
		t2.start();
	}}

3. 同期コード ブロック synchronized

Java 同時(shí)プログラミングとスレッド セーフの基本の概要

synchronized の理解

//次のコード行はスレッドによってキューに入れられる必要があり、キューに入れることはできません。同時(shí)実行性

//

1つのスレッドがここにあるすべてのコードの実行を終了した後、別のスレッドが入ることができます /*

スレッド同期メカニズムの構(gòu)文は
synchronized ( ){ //スレッド同期コードブロック。
}
同期後に括弧內(nèi)に渡されるデータは非常に重要です。
マルチスレッド キューイングを?qū)g現(xiàn)するには、このデータを複數(shù)のスレッドで共有する必要があります。

()內(nèi)には何が書かれていますか?
どのスレッドを同期するかによって異なります。
t1、t2、t3、t4、および t5 に 5 つのスレッドがあると仮定します。
t1 t2 t3 のみをキューに入れたいが、t4 t5 はキューに入れないようにする必要があります。キューに入れる必要があります。どうすればよいですか () 內(nèi)に t1 t2 t3 によって共有されるオブジェクトを記述する必要がありますが、このオブジェクトは t4 t5 によって共有されません ここでの共有オブジェクトはアカウント オブジェクトです
アカウント オブジェクトは共有されており、これがアカウントです。オブジェクト
は、複數(shù)のスレッドで共有されるオブジェクトである限り、これである必要がない場(chǎng)合があります

		synchronized(this){
			double?before=this.getBalance();
			double?after=before-money;
			try?{
				Thread.sleep(1000);
			}?catch?(InterruptedException?e)?{
				//?TODO?Auto-generated?catch?block
				e.printStackTrace();
			}
			this.setBalance(after);
		}

Java 同時(shí)プログラミングとスレッド セーフの基本の概要
在java語(yǔ)言中,任何對(duì)象都有一把鎖,其實(shí)這把鎖就是一個(gè)標(biāo)記,(只是把它叫做鎖)
100個(gè)對(duì)象,100個(gè)鎖,1個(gè)對(duì)象1把鎖。
以上代碼的執(zhí)行原理是什么呢?
1.假設(shè)t1和t2線程并發(fā),開始執(zhí)行以上代碼的時(shí)候,肯定有一個(gè)先一個(gè)后,
2.假設(shè)t1先執(zhí)行了,遇到了synchronized,這個(gè)時(shí)候自動(dòng)找后面共享對(duì)象的對(duì)象鎖,找到之后,并占有這把鎖,然后執(zhí)行同步代碼塊中的程序,在程序執(zhí)行過程中一直都占有這把鎖,直到同步代碼塊執(zhí)行結(jié)束,這把鎖才會(huì)釋放。
3.假設(shè)t1已經(jīng)占有這把鎖,此時(shí)t2也遇到synchronized關(guān)鍵字,也會(huì)去占有后面共享對(duì)象的這把鎖,結(jié)果這把鎖被t1占有,t2只能在同步代碼塊外邊等待t1的結(jié)束,直到t1把同步代碼塊執(zhí)行結(jié)束了,t1會(huì)歸還這把鎖,此時(shí)t2終于等到這把鎖,然后t2占有這把鎖之后,進(jìn)入同步代碼塊執(zhí)行程序。
這樣就達(dá)到了線程排隊(duì)執(zhí)行
這里需要注意的是:這個(gè)共享對(duì)象一定要選好了,這個(gè)共享對(duì)象一定是你需要排隊(duì)執(zhí)行的這些線程對(duì)象所共享的。
//對(duì)象
Object obj=new Object(); //實(shí)例變量(Account對(duì)象是多線程共享的,Account對(duì)象中的實(shí)例變量obj也是共享的)
synchronized(obj){}

Java 同時(shí)プログラミングとスレッド セーフの基本の概要
括號(hào)里邊只要是共享對(duì)象就行。
Object obj2=new Object(); //局部變量
synchronized(obj2){}
這樣寫就不安全了,因?yàn)閛bj2是局部變量,不是共享對(duì)象。
synchronized(“abc”){}
這樣寫時(shí)可以的。存在字符串常量池中
寫"abc"的話所有線程都會(huì)同步

而如果是寫synchronized(this){}的話,我們創(chuàng)建了一個(gè)新的對(duì)象act2可不用共享對(duì)象。
所以最好是寫synchronized(this){},比如你要取款,要讓其他取別的賬戶的人也要等嗎?不應(yīng)該,只有同時(shí)對(duì)你這1個(gè)賬戶取款的時(shí)候,需要等待,別人取錢的時(shí)候,需要從其他賬戶中取錢,就不需要等待。

java中有三大變量的線程安全問題

實(shí)例變量,在堆中
靜態(tài)變量,在方法區(qū)
局部變量,在棧中

以上三大變量
局部變量永遠(yuǎn)不會(huì)存在線程安全問題
因?yàn)榫植孔兞坎还蚕恚ㄒ粋€(gè)線程一個(gè)棧)
局部變量在棧中,所以局部變量永遠(yuǎn)都不會(huì)共享
實(shí)例變量在堆中,堆只有1個(gè)。
靜態(tài)變量在方法區(qū)中,方法區(qū)只有1個(gè)
。
堆和方法區(qū)都是多線程共享的,所以可能存在線程安全問題。

局部變量+常量:不會(huì)有線程安全問題。
成員變量:可能會(huì)有線程安全問題
。

同步代碼塊越小,效率越高。

//多線程執(zhí)行這個(gè)方法//synchronized(this)//這里的this是AccountThread對(duì)象,這個(gè)對(duì)象不共享。synchronized(act){
			act.withdraw(money);
			System.out.println(Thread.currentThread().getName()+"賬戶"+act.getActno()+"取款成功,余額:"+act.getBalance());}

在實(shí)例方法上使用synchronized

在實(shí)例方法上可以使用synchronized嗎?可以的。
synchronized出現(xiàn)在實(shí)例方法上,一定鎖的是this
沒得挑,只能是this,不能是其他的對(duì)象了
所以這種方式不靈活。
另外還有一個(gè)缺點(diǎn):synchronized出現(xiàn)在實(shí)例方法上,表示整個(gè)方法體都需要同步
可能會(huì)擴(kuò)大同步的范圍,導(dǎo)致程序的執(zhí)行效率降低。所以這種方式不常用
synchronized使用在實(shí)例方法上有什么優(yōu)點(diǎn)?
代碼寫的少了,節(jié)儉了。
如果共享的對(duì)象是this,并且需要同步的代碼是整個(gè)方法體,建議使用這種方式。
StringBuffer就是在每個(gè)方法上加了synchronized關(guān)鍵字

使用局部變量的話,最好使用StringBuilder
因?yàn)榫植孔兞坎淮嬖诰€程安全問題,選擇StringBuilder,StringBuffer效率比較低。
ArrayList是非線程安全的。
Vector是線程安全的。
HashMap HashSet是非線程安全的。
Hashtable是線程安全的
。

總結(jié)

synchronized有三種寫法:

??第一種:同步代碼塊
????靈活
??????synchronized(線程共享對(duì)象){
????????同步代碼塊;
??????}
??第二種:在實(shí)例方法上使用synchronized
??????表示共享對(duì)象一定是this
??????并且同步代碼塊是整個(gè)方法體。
??第三種:在靜態(tài)方法上使用synchronized
??????表示找類鎖。
??????類鎖永遠(yuǎn)只有1把。
??????就算創(chuàng)建了100個(gè)對(duì)象,那類鎖也只有一把。

對(duì)象鎖:1個(gè)對(duì)象1把鎖,100個(gè)對(duì)象100把鎖。
類鎖:100個(gè)對(duì)象,也可能只是1把類鎖。

面試題

//面試題:doother方法的執(zhí)行需不需要等待dosome方法的結(jié)束。
//不需要,因?yàn)閐oother方法沒有synchronized

public?class?exam01?{
	public?static?void?main(String[]?args)?{
		MyClass?mc=new?MyClass();
		Thread?t1=new?MyThread(mc);
		Thread?t2=new?MyThread(mc);
		t1.setName("t1");
		t2.setName("t2");
		t1.start();
		try?{
			Thread.sleep(1000);		//這個(gè)睡眠的作用是:為了保證t1線程先執(zhí)行
		}?catch?(InterruptedException?e)?{
			//?TODO?Auto-generated?catch?block
			e.printStackTrace();
		}
		t2.start();
	}}class?MyThread?extends?Thread{
	private?MyClass?mc;
	public?MyThread(MyClass?mc)?{
		super();
		this.mc?=?mc;
	}
	public?void?run(){
		if(Thread.currentThread().getName().equals("t1")){
			mc.dosome();
		}
		if(Thread.currentThread().getName().equals("t2")){
			mc.doOther();
		}
	}
	}class?MyClass{
	public?synchronized?void?dosome(){
		System.out.println("doSome?begin");
		try?{
			Thread.sleep(1000);
		}?catch?(InterruptedException?e)?{
			//?TODO?Auto-generated?catch?block
			e.printStackTrace();
		}
		System.out.println("doSome?end");
	}
	public?void?doOther(){
		System.out.println("doOther?begin");
		System.out.println("doOther?end");
	}}

Java 同時(shí)プログラミングとスレッド セーフの基本の概要
當(dāng)在doother上面加了synchronized呢
//面試題:doother方法的執(zhí)行需不需要等待dosome方法的結(jié)束。
//需要,因?yàn)閐oother方法沒有synchronized

	public?synchronized?void?doOther(){
		System.out.println("doOther?begin");
		System.out.println("doOther?end");
	}

//面試題:doother方法的執(zhí)行需不需要等待dosome方法的結(jié)束。
//不用排隊(duì),誰(shuí)也不用管誰(shuí)

MyClass?mc1=new?MyClass();MyClass?mc2=new?MyClass();Thread?t1=new?MyThread(mc1);Thread?t2=new?MyThread(mc2);

//面試題:doother方法的執(zhí)行需不需要等待dosome方法的結(jié)束。
//需要,因?yàn)殪o態(tài)方法是類鎖,類鎖不管創(chuàng)建了幾個(gè)對(duì)象,類鎖只有一把

MyClass?mc1=new?MyClass();MyClass?mc2=new?MyClass();Thread?t1=new?MyThread(mc1);Thread?t2=new?MyThread(mc2);public?synchronized?static?void?dosome(){
		System.out.println("doSome?begin");
		try?{
			Thread.sleep(1000);
		}?catch?(InterruptedException?e)?{
			//?TODO?Auto-generated?catch?block
			e.printStackTrace();
		}
		System.out.println("doSome?end");
	}
	public?synchronized?static?void?doOther(){
		System.out.println("doOther?begin");
		System.out.println("doOther?end");
	}

這種鎖叫排他鎖:

4.死鎖

Java 同時(shí)プログラミングとスレッド セーフの基本の概要
synchronized在開發(fā)中最好不要嵌套使用,一不小心就可能導(dǎo)致死鎖。
死鎖代碼要會(huì)寫。
一般面試官要求你會(huì)寫
只有會(huì)寫的,才會(huì)在以后的開發(fā)中注意這個(gè)事兒
因?yàn)樗梨i很難調(diào)試。

public?class?DeadLock?{
	public?static?void?main(String[]?args)?{
		Object?o1=new?Object();
		Object?o2=new?Object();
		//t1線程和t2線程共享o1,o2
		Thread?t1=new?MyThread1(o1,o2);
		Thread?t2=new?MyThread2(o1,o2);
		t1.start();
		t2.start();
	}}class?MyThread1?extends?Thread{
	Object?o1;
	Object?o2;
	public?MyThread1(Object?o1,Object?o2){
		this.o1=o1;
		this.o2=o2;
	}
	@Override
	public?void?run()?{
		synchronized?(o1)?{
			try?{
				Thread.sleep(1000);
			}?catch?(InterruptedException?e)?{
				//?TODO?Auto-generated?catch?block
				e.printStackTrace();
			}
			synchronized?(o2)?{
				
			}
		}
	}}class?MyThread2?extends?Thread{
	Object?o1;
	Object?o2;
	public?MyThread2(Object?o1,Object?o2){
		this.o1=o1;
		this.o2=o2;
	}
	@Override
	public?void?run()?{
		synchronized?(o2)?{
			try?{
				Thread.sleep(1000);
			}?catch?(InterruptedException?e)?{
				//?TODO?Auto-generated?catch?block
				e.printStackTrace();
			}
			synchronized?(o1)?{
				
			}
		}
	}}

5.開發(fā)中應(yīng)該怎么解決線程安全問題

聊一聊,我們以后開發(fā)中應(yīng)該怎么解決線程安全問題?
??是一上來就選擇線程同步嗎?synchronized
??不是,synchronized會(huì)讓程序的執(zhí)行效率降低,用戶體驗(yàn)不好。
??系統(tǒng)的用戶吞吐量降低。用戶體驗(yàn)差。在不得已的情況下再選擇
??線程同步機(jī)制。
??第一種方案:盡量使用局部變量代替“實(shí)例變量和靜態(tài)變量”。
??第二種方案:如果必須是實(shí)例變量,那么可以考慮創(chuàng)建多個(gè)對(duì)象,這樣實(shí)例變量的內(nèi)存就不共享了。(一個(gè)線程對(duì)應(yīng)1個(gè)對(duì)象,100個(gè)線程對(duì)應(yīng)100個(gè)對(duì)象,對(duì)象不共享,就沒有數(shù)據(jù)安全問題了。)
??第三種方案:如果不能使用局部變量,對(duì)象也不能創(chuàng)建多個(gè),這個(gè)時(shí)候就只能選擇synchronized了。線程同步機(jī)制
線程這塊還有那些內(nèi)容呢?列舉一下
7.1、守護(hù)線程
7.2、定時(shí)器
7.3、實(shí)現(xiàn)線程的第三種方式:FutureTask方式,實(shí)現(xiàn)Callable接口。(JDK8新特性。)
7.4、關(guān)于Object類中的wait和notify方法。(生產(chǎn)者和消費(fèi)者模式!)

6.守護(hù)線程

守護(hù)線程
java語(yǔ)言中線程分為兩大類:
??一類是:用戶線程
??一類是:守護(hù)線程(后臺(tái)線程)

其中具有代表性的就是:垃圾回收線程(守護(hù)線程)。
??守護(hù)線程的特點(diǎn):
??一般守護(hù)線程是一個(gè)死循環(huán),所有的用戶線程只要結(jié)束,
??守護(hù)線程自動(dòng)結(jié)束。
??注意:主線程main方法是一個(gè)用戶線程。
??守護(hù)線程用在什么地方呢?
??每天00:00的時(shí)候系統(tǒng)數(shù)據(jù)自動(dòng)備份。
??這個(gè)需要使用到定時(shí)器,并且我們可以將定時(shí)器設(shè)置為守護(hù)線程。
??一直在那里看著,沒到00:00的時(shí)候就備份一次。所有的用戶線程如果結(jié)束了,守護(hù)線程自動(dòng)退出,沒有必要進(jìn)行數(shù)據(jù)備份了。

package?testThread;/*
實(shí)現(xiàn)守護(hù)線程
?*?*/
	public?class?ThreadTest13?{

	public?static?void?main(String[]?args)?{
		//?TODO?Auto-generated?method?stub
		Thread?t=new?BakDataThread();
		t.setName("備份數(shù)據(jù)的線程");
		//啟動(dòng)之前,將線程設(shè)置為守護(hù)線程
		t.setDaemon(true);
		t.start();
		//主線程:主線程是用戶線程
		for(int?i=0;i"+i);
			try?{
				Thread.sleep(1000);
			}?catch?(Exception?e)?{
				//?TODO:?handle?exception
			}
		}
	}}class?BakDataThread?extends?Thread{
	@Override
	public?void?run()?{
		int?i=0;
		//即使是死循環(huán),但由于該線程是守護(hù)者,當(dāng)用戶線程結(jié)束,守護(hù)線程自動(dòng)終止
		while(true){
			System.out.println(Thread.currentThread().getName()+"---->"+(++i));
			try?{
				Thread.sleep(1000);
			}?catch?(Exception?e)?{
				//?TODO:?handle?exception
			}
			
		}
	}}

7.定時(shí)器

定時(shí)器的作用:
??間隔特定的時(shí)間,執(zhí)行特定的程序。
??每周要進(jìn)行銀行賬戶的總賬操作。
??每天要進(jìn)行數(shù)據(jù)的備份操作。
??在實(shí)際的開發(fā)中,每隔多久執(zhí)行一段特定的程序,這種需求是很常見的,
那么在java中其實(shí)可以采用多種方式實(shí)現(xiàn):
??可以使用sleep方法,睡眠,設(shè)置睡眠時(shí)間,沒到這個(gè)時(shí)間點(diǎn)醒來,執(zhí)行任務(wù)。這種方式是最原始的定時(shí)器。(比較low)
??在java的類庫(kù)中已經(jīng)寫好了一個(gè)定時(shí)器:java.util.Timer,可以直接拿來用。不過,這種方式在目前的開發(fā)中也很少用,因?yàn)楝F(xiàn)在有很多高級(jí)框架都是支持定時(shí)任務(wù)的。

??在實(shí)際的開發(fā)中,目前使用較多的是Spring框架中提供的SpringTask框架,這個(gè)框架只要進(jìn)行簡(jiǎn)單的配置,就可以完成定時(shí)器的任務(wù)。

8.實(shí)現(xiàn)線程的第三種方式:實(shí)現(xiàn)Callable接口

實(shí)現(xiàn)線程的第三種方式:實(shí)現(xiàn)Callable接口。(JDK8新特性。)
這種方式實(shí)現(xiàn)的線程可以獲取線程的返回值。
之前講解的那兩種方式是無法獲取線程返回值的,因?yàn)閞un方法返回void。
思考:
系統(tǒng)委派一個(gè)線程去執(zhí)行一個(gè)任務(wù),該線程執(zhí)行完任務(wù)之后,可能會(huì)有一個(gè)執(zhí)行結(jié)果,我們?cè)趺茨苣玫竭@個(gè)執(zhí)行結(jié)果呢?
使用第三種方式:實(shí)現(xiàn)Callable接口方式。

public?class?ThreadTest14?{
	public?static?void?main(String[]?args)?throws?Exception,?ExecutionException?{
		//第一步:創(chuàng)建一個(gè)未來任務(wù)類對(duì)象
		//參數(shù)非常重要,需要給一個(gè)callable接口的實(shí)現(xiàn)類對(duì)象
		FutureTask?task=new?FutureTask(new?Callable(){
			@Override
			//call方法相當(dāng)于是run方法,只不過這個(gè)有返回值,線程執(zhí)行一個(gè)任務(wù),執(zhí)行之后可能會(huì)有一個(gè)執(zhí)行結(jié)果。
			public?Object?call()?throws?Exception?{
				System.out.println("call?method?begin");
				Thread.sleep(1000);
				System.out.println("call?method?begin");
				int?a=100;
				int?b=200;
				return?a+b;			//自動(dòng)裝箱
			}		
		});
		//創(chuàng)建線程對(duì)象
		Thread?t=new?Thread(task);
		
		//啟動(dòng)線程
		t.start();
		
		//這里是main方法,這是在主線程中
		//在線程中,怎么獲取t線程的執(zhí)行結(jié)果
		//get方法的執(zhí)行會(huì)導(dǎo)致當(dāng)前線程阻塞
		Object?obj=task.get();
		System.out.println("線程執(zhí)行結(jié)果"+obj);
		//main方法這里的程序要想執(zhí)行必須等待get()方法的結(jié)束
		//而get方法可能需要很久。因?yàn)間et()方法是為了拿另一個(gè)線程的執(zhí)行結(jié)果。
		//另一個(gè)線程的執(zhí)行是需要時(shí)間的
		System.out.println("hello,world");
	}}

這種方式的優(yōu)點(diǎn):可以獲取到線程的執(zhí)行結(jié)果
這種方式的缺點(diǎn):效率比較低,在獲取t線程執(zhí)行結(jié)果的時(shí)候,當(dāng)前線程受阻塞,效率較低。

9.Object類中的wait和notify方法

(生產(chǎn)者和消費(fèi)者模式!)
??第一:wait和notify方法不是線程對(duì)象的方法,是java中任何一個(gè)java對(duì)象都有的方法,因?yàn)檫@兩個(gè)方式是Object類中自帶的。
??wait方法和notify方法不是通過線程對(duì)象調(diào)用,

??不是這樣的:t.wait(),也不是這樣的:t.notify()…不對(duì)。
??第二:wait()方法作用?
????Object o = new Object();
????o.wait();
??表示:
??讓正在o對(duì)象上活動(dòng)的線程進(jìn)入等待狀態(tài),無期限等待,直到被喚醒為止。
??o.wait();方法的調(diào)用,會(huì)讓“當(dāng)前線程(正在o對(duì)象上活動(dòng)的線程)”進(jìn)入等待狀態(tài)
??第三:notify()方法作用?
????Object o = new Object();
????o.notify();
??表示:
??喚醒正在o對(duì)象上等待的線程
??還有一個(gè)notifyAll()方法:
??這個(gè)方法是喚醒o對(duì)象上處于等待的所有線程。

Java 同時(shí)プログラミングとスレッド セーフの基本の概要

10.生產(chǎn)者和消費(fèi)者

Java 同時(shí)プログラミングとスレッド セーフの基本の概要
1.使用wait方法和notify方法實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者模式
2.什么是生產(chǎn)者和消費(fèi)者模式?
生產(chǎn)線程負(fù)責(zé)生產(chǎn),消費(fèi)線程負(fù)責(zé)消費(fèi)
生產(chǎn)線程和消費(fèi)線程要達(dá)到均衡
這是一種特殊的業(yè)務(wù)需求,在這種特殊的情況下需要使用wait方法和notify方法
3.wait和notify方法不是線程對(duì)象的方法,是普通java對(duì)象都有的方法
4.wait方法和notify方法是建立在線程同步的基礎(chǔ)之上。因?yàn)槎嗑€程要同時(shí)操作一個(gè)倉(cāng)庫(kù),有線程安全問題
5.wait方法作用:o.wait()讓正在o對(duì)象上活動(dòng)的線程t進(jìn)入等待狀態(tài),并且釋放掉t線程之前占有的o對(duì)象的鎖
6.notify方法的作用:o.notify()讓正在o對(duì)象上等待的線程喚醒,只是5通知,不會(huì)釋放o對(duì)象上之前占有的鎖
7.模擬這樣一個(gè)需求:
倉(cāng)庫(kù)我們采用list集合
list集合中假設(shè)只能存儲(chǔ)1個(gè)元素
1個(gè)元素就表示倉(cāng)庫(kù)滿了
如果list集合中的元素個(gè)數(shù)是0,就表示倉(cāng)庫(kù)空了。
保證list集合中永遠(yuǎn)都是最多存儲(chǔ)1個(gè)元素
必須做到這種效果,生產(chǎn)1個(gè)消費(fèi)1個(gè)。

public?class?ThreadTest15?{
	public?static?void?main(String[]?args)?{
		//創(chuàng)建一個(gè)倉(cāng)庫(kù)獨(dú)享,共享的
		List?list=new?ArrayList();
		//創(chuàng)建兩個(gè)線程對(duì)象
		//生產(chǎn)者線程
		Thread?t1=new?Thread(new?Producer(list));
		//消費(fèi)者線程
		Thread?t2=new?Thread(new?Consumer(list));
		t1.setName("生產(chǎn)者線程");
		t2.setName("消費(fèi)者線程");
		t1.start();
		t2.start();
	}}//生產(chǎn)線程class?Producer?implements?Runnable{
	//倉(cāng)庫(kù)
	private?List?list;
	public?Producer(List?list)?{
		this.list?=?list;
	}
	public?void?run()?{
		//一直生產(chǎn)
		while(true){
			//給倉(cāng)庫(kù)對(duì)象list加鎖
			synchronized?(list)?{
				if(list.size()>0){	//大于0說明倉(cāng)庫(kù)中已經(jīng)有1個(gè)元素了
					//當(dāng)前線程進(jìn)入等待狀態(tài),并且釋放list集合的鎖
					try?{
						list.wait();
					}?catch?(InterruptedException?e)?{
						//?TODO?Auto-generated?catch?block
						e.printStackTrace();
					}
				}
				//程序能夠執(zhí)行到這里說明倉(cāng)庫(kù)是空的,可以生產(chǎn)
				Object?obj?=new?Object();
				list.add(obj);
				System.out.println(Thread.currentThread().getName()+"---->"+obj);
				//喚醒消費(fèi)者進(jìn)行消費(fèi)
				list.notifyAll();
			}
			
		}
	}}//消費(fèi)線程class?Consumer?implements?Runnable{
	//倉(cāng)庫(kù)
	private?List?list;
	public?Consumer(List?list)?{
		this.list?=?list;
	}
	public?void?run()?{
		//一直消費(fèi)
		while(true){
			//給倉(cāng)庫(kù)對(duì)象list加鎖
			synchronized?(list)?{
				if(list.size()==0){	//倉(cāng)里已經(jīng)空了
					try?{
						//倉(cāng)庫(kù)已經(jīng)空了
						//消費(fèi)者線程等待,并釋放掉list集合鎖
						list.wait();
					}?catch?(InterruptedException?e)?{
						//?TODO?Auto-generated?catch?block
						e.printStackTrace();
					}
				}
			}
			Object?obj=list.remove(0);
			System.out.println(Thread.currentThread().getName()+"---->"+obj);
			//喚醒生產(chǎn)者生產(chǎn)
			list.notifyAll();
		}
	}}

相關(guān)學(xué)習(xí)推薦:java基礎(chǔ)

以上がJava 同時(shí)プログラミングとスレッド セーフの基本の概要の詳細(xì)內(nèi)容です。詳細(xì)については、PHP 中國(guó)語(yǔ) Web サイトの他の関連記事を參照してください。

このウェブサイトの聲明
この記事の內(nèi)容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰屬します。このサイトは、それに相當(dāng)する法的責(zé)任を負(fù)いません。盜作または侵害の疑いのあるコンテンツを見つけた場(chǎng)合は、admin@php.cn までご連絡(luò)ください。

ホットAIツール

Undress AI Tool

Undress AI Tool

脫衣畫像を無料で

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

寫真から衣服を削除するオンライン AI ツール。

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡(jiǎn)単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中國(guó)語(yǔ)版

SublimeText3 中國(guó)語(yǔ)版

中國(guó)語(yǔ)版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強(qiáng)力な PHP 統(tǒng)合開発環(huán)境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

JDBCを使用してJavaのトランザクションを処理する方法は? JDBCを使用してJavaのトランザクションを処理する方法は? Aug 02, 2025 pm 12:29 PM

JDBCトランザクションを正しく処理するには、最初に自動(dòng)コミットモードをオフにし、次に複數(shù)の操作を?qū)g行し、結(jié)果に応じて最終的にコミットまたはロールバックする必要があります。 1。CONN.SETAUTOCOMMIT(FALSE)を呼び出して、トランザクションを開始します。 2。挿入や更新など、複數(shù)のSQL操作を?qū)g行します。 3。すべての操作が成功した場(chǎng)合はconn.commit()を呼び出し、データの一貫性を確保するために例外が発生した場(chǎng)合はconn.rollback()を呼び出します。同時(shí)に、リソースを使用してリソースを管理し、例外を適切に処理し、接続を密接に接続するために、接続の漏れを避けるために使用する必要があります。さらに、接続プールを使用してセーブポイントを設(shè)定して部分的なロールバックを達(dá)成し、パフォーマンスを改善するためにトランザクションを可能な限り短く保つことをお?jiǎng)幛幛筏蓼埂?/p>

Javaでカレンダーを操作する方法は? Javaでカレンダーを操作する方法は? Aug 02, 2025 am 02:38 AM

Java.Timeパッケージのクラスを使用して、古い日付とカレンダーのクラスを置き換えます。 2。LocalDate、LocalDateTime、LocalTimeを通じて現(xiàn)在の日付と時(shí)刻を取得します。 3。of()メソッドを使用して特定の日付と時(shí)刻を作成します。 4.プラス/マイナスメソッドを使用して、時(shí)間を不正に増加させて短縮します。 5. ZonedDateTimeとZoneIDを使用して、タイムゾーンを処理します。 6。DateTimeFormatterを介したフォーマットおよび解析の文字列。 7.インスタントを使用して、必要に応じて古い日付型と互換性があります。現(xiàn)代のJavaでの日付処理は、java.timeapiを使用することを優(yōu)先する必要があります。

Javaフレームワークの比較:Spring Boot vs Quarkus vs Micronaut Javaフレームワークの比較:Spring Boot vs Quarkus vs Micronaut Aug 04, 2025 pm 12:48 PM

Pre-formanceTartuptimeMemoryusage、quarkusandmicronautleadduetocopile-timeprocessingingandgraalvsupport、withquarkusoftentylightbetterine serverlessシナリオ。

Garbage CollectionはJavaでどのように機(jī)能しますか? Garbage CollectionはJavaでどのように機(jī)能しますか? Aug 02, 2025 pm 01:55 PM

JavaのGarbage Collection(GC)は、メモリを自動(dòng)的に管理するメカニズムであり、到達(dá)不可能なオブジェクトを取り戻すことでメモリ漏れのリスクを軽減します。 1.GCルートオブジェクトからのオブジェクトのアクセシビリティ(スタック変數(shù)、アクティブスレッド、靜的フィールドなど)、および到達(dá)不可能なオブジェクトはゴミとしてマークされています。 2。マーククリアリングアルゴリズムに基づいて、すべての到達(dá)可能なオブジェクトをマークし、マークのないオブジェクトをクリアします。 3.世代の収集戦略を採(cǎi)用する:新世代(Eden、S0、S1)は頻繁にMinorGCを?qū)g行します。高齢者のパフォーマンスは少なくなりますが、MajorGCを?qū)g行するのに時(shí)間がかかります。 Metaspaceはクラスメタデータを保存します。 4。JVMはさまざまなGCデバイスを提供します。SerialGCは小さなアプリケーションに適しています。 ParallelGCはスループットを改善します。 CMSが減少します

Javaビルドツールの比較:Maven vs. Gradle Javaビルドツールの比較:Maven vs. Gradle Aug 03, 2025 pm 01:36 PM

gradleisthebetterchoiceformostnewprojectoitssuperorfficability、performance、andmoderntoolingsupport.1.gradle’sgroovy/kotlindslismoreconciseandexpressiveethanmaven’sverboseml.2.gradleorformsmavenbenbumebutedwitedwitedwitedspedexは

説明された延期聲明の例で進(jìn)みます 説明された延期聲明の例で進(jìn)みます Aug 02, 2025 am 06:26 AM

Deferは、クリーニングリソースなど、関數(shù)が戻る前に指定された操作を?qū)g行するために使用されます。パラメーターは、延期時(shí)にすぐに評(píng)価され、関數(shù)は最後のファーストアウト(LIFO)の順に実行されます。 1.複數(shù)の債務(wù)は、宣言の逆の順序で実行されます。 2.ファイルの閉鎖などの安全なクリーニングに一般的に使用されます。 3。指定された返品値を変更できます。 4.回復(fù)に適したパニックが発生した場(chǎng)合でも実行されます。 5。リソースの漏れを防ぐために、ループで延期の亂用を避けます。正しい使用により、コードのセキュリティと読みやすさが向上します。

ユーザーデータにHTML「入力」タイプを使用します ユーザーデータにHTML「入力」タイプを使用します Aug 03, 2025 am 11:07 AM

適切なHTMLinputタイプを選択すると、データの精度を向上させ、ユーザーエクスペリエンスを向上させ、使いやすさを向上させることができます。 1.テキスト、電子メール、電話、番號(hào)、日付など、データ型に従って対応する入力タイプを選択します。 2。HTML5を使用して、より直感的な相互作用方法を提供できるU(xiǎn)RL、色、範(fàn)囲、検索などの新しいタイプを追加します。 3.プレースホルダーと必要な屬性を使用して、フォームフィリングの効率と精度を改善しますが、プレースホルダーがラベルを置き換えることはできないことに注意してください。

HTTPミドルウェアロギングの例を例に進(jìn)めます HTTPミドルウェアロギングの例を例に進(jìn)めます Aug 03, 2025 am 11:35 AM

GOのHTTPログミドルウェアは、リクエストメソッド、パス、クライアントIP、および時(shí)間がかかることを記録できます。 1. http.handlerfuncを使用してプロセッサをラップします。2。next.servehttpを呼び出す前後の開始時(shí)間と終了時(shí)間を記録します。完全なサンプルコードの実行が検証されており、中小のプロジェクトの開始に適しています。拡張機(jī)能の提案には、ステータスコードのキャプチャ、JSONログのサポート、リクエストIDトラッキングが含まれます。

See all articles