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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java多线程多态_Java学习之多线程

發(fā)布時間:2024/9/27 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java多线程多态_Java学习之多线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

多線程:

(一)進程與線程

進程特點

并發(fā)與并行的區(qū)別:

多線程編程的好處:

(二)多線程的建立

1,通過繼承Thread類,代碼如下:

class MyThread extendsThread {private static int K = 10;//類共享變量

private int M=10;//成員共享變量

MyThread(){super();

}

@Overridepublic voidrun() {

System.out.println("in MyThread run");for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+ "K:" + K--);

System.out.println(Thread.currentThread().getName()+ "M:" + M--);

}

}

}public classThreadDemo1 {public static voidmain(String[] args) {//多線程Thead方式1

MyThread thread2 = newMyThread();new Thread(thread2,"t2").start();//此時成員變量被共享,靜態(tài)也被共享,k和M的結果為-9

new Thread(thread2,"t3").start();//多線程Thead方式1

MyThread thread3=new MyThread();//此時靜態(tài)類變量被共享,k為-9,M為0.

thread2.start();

thread3.start();

}

}

2,通過實現Runnable接口(推薦),代碼如下:

public classThreadDemo1 {public static voidmain(String[] args) {//RUNNABLE 方式2

MyRunnable myRunnable = newMyRunnable();new Thread(myRunnable,"t1").start();//此時成員變量被共享,靜態(tài)也被共享,K和M為-9//RUNNABLE 方式2

new Thread(myRunnable,"t3").start();

MyRunnable myRunnable1= new MyRunnable();//此時成員變量不被共享,靜態(tài)被共享,K為-9,M為0

new Thread(myRunnable,"t1").start();new Thread(myRunnable1,"t3").start();

}

}class MyRunnable implementsRunnable {private static int K = 10;private int M = 10;

@Overridepublic voidrun() {

System.out.println("in MyRunnable run");for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+ " K:" + (K--));

System.out.println(Thread.currentThread().getName()+ " M:" + (M--));

}

}

}

3,通過實現Callable接口和Future包裝來建立:

importjava.util.Random;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.FutureTask;public classCallableThread {public static voidmain(String[] args) {

Callable callable = new Callable() {public Integer call() throwsException {return new Random().nextInt(100);

}

};

FutureTask future = new FutureTask(callable);newThread(future).start();try{

Thread.sleep(5000);//可能做一些事情

System.out.println(future.get());

}catch(InterruptedException e) {

e.printStackTrace();

}catch(ExecutionException e) {

e.printStackTrace();

}

}

}

View Code

三種建立多線程的優(yōu)劣比較有:

(三)線程的生命周期

Java線程具有五中基本狀態(tài)

新建狀態(tài)(New):當線程對象對創(chuàng)建后,即進入了新建狀態(tài),如:Thread t = new MyThread();

就緒狀態(tài)(Runnable):當調用線程對象的start()方法(t.start();),線程即進入就緒狀態(tài)。處于就緒狀態(tài)的線程,只是說明此線程已經做好了準備,隨時等待CPU調度執(zhí)行,并不是說執(zhí)行了t.start()此線程立即就會執(zhí)行;

運行狀態(tài)(Running):當CPU開始調度處于就緒狀態(tài)的線程時,此時線程才得以真正執(zhí)行,即進入到運行狀態(tài)。注:就 ? ? 緒狀態(tài)是進入到運行狀態(tài)的唯一入口,也就是說,線程要想進入運行狀態(tài)執(zhí)行,首先必須處于就緒狀態(tài)中;

阻塞狀態(tài)(Blocked):處于運行狀態(tài)中的線程由于某種原因,暫時放棄對CPU的使用權,停止執(zhí)行,此時進入阻塞狀態(tài),直到其進入到就緒狀態(tài),才 有機會再次被CPU調用以進入到運行狀態(tài)。根據阻塞產生的原因不同,阻塞狀態(tài)又可以分為三種:

1.等待阻塞:運行狀態(tài)中的線程執(zhí)行wait()方法,使本線程進入到等待阻塞狀態(tài);

2.同步阻塞 -- 線程在獲取synchronized同步鎖失敗(因為鎖被其它線程所占用),它會進入同步阻塞狀態(tài);

3.其他阻塞 -- 通過調用線程的sleep()或join()或發(fā)出了I/O請求時,線程會進入到阻塞狀態(tài)。當sleep()狀態(tài)超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態(tài)。

死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法,該線程結束生命周期。

關鍵字:

yield:該線程讓出CPU,進入就緒狀態(tài)

join:該子線程優(yōu)先執(zhí)行,相當于方法調用,父線程進入IO阻塞狀態(tài)

sleep:該線程讓出CPU,進入IO阻塞狀態(tài),不釋放對象鎖

wait:同步鎖下進行使用,該線程進入阻塞狀態(tài),釋放對象鎖

notify:喚醒wait下的線程,進入同步阻塞狀態(tài)

synchronized:同步鎖,未獲得鎖的線程進入同步阻塞狀態(tài)

(五),多線程同步(Thread Synchronized)

線程同步即保證某個線程訪問某個共享資源時,其他的線程需要wait,即有順序性

(六),多線程案例

1,線程死鎖案例:

/*死鎖:

線程1:synchronized(o1) { Thread.sleep() synchronized(o2) }

線程2:synchronized(o2) { Thread.sleep() synchronized(o1) }

首先線程1執(zhí)行,對o1加同步鎖,其他線程無法訪問,

然后線程1睡眠,讓出cpu,線程2執(zhí)行,鎖住o2

線程1睡眠結束,繼續(xù)執(zhí)行,要對o2加同步鎖,但被線程2占據,所以上不了鎖,

處于等待獲得o2同步鎖的狀態(tài),且線程1不能結束,釋放不了o1對象。

線程2睡眠結束,繼續(xù)執(zhí)行,要對o1加同步鎖,但被線程1占據,所以上不了鎖,

處于等待獲得o1同步鎖的狀態(tài),且線程2不能結束,故釋放不了o2

故處于死鎖狀態(tài)。

死鎖經典問題:哲學家問題

方法:加粗鎖定對象*/

public class DeadThread implementsRunnable {private int flag=0;static Object object=new Object();//類變量,只有一份,每個實例共享

static Object object1=new Object();// public voidrun(){if (flag==0){synchronized (object) {//釋放object同步鎖,需要等object1鎖釋放,

System.out.println(flag);try{

Thread.sleep(40);

}catch(InterruptedException e) {

e.printStackTrace();

}synchronized(object1) {//System.out.println(flag);

}

}

}if (flag==1){synchronized (object1) {//釋放object1同步鎖,需要等object鎖釋放.兩個線程互相等待中

System.out.println(flag);try{

Thread.sleep(400);

}catch(InterruptedException e) {

e.printStackTrace();

}synchronized(object) {//System.out.println(flag);

}

}

}

}public static voidmain(String[] args) {

DeadThread deadThread=newDeadThread();

DeadThread deadThread1=newDeadThread();

deadThread.flag=0;

deadThread.flag=1;

Thread thread=newThread(deadThread);

Thread thread1=newThread(deadThread1);

thread.start();

thread1.start();

}

}

2,多線程多態(tài):

public classThreadTest {public static voidmain(String[] args) {for (int i = 0; i < 100; i++) {

System.out.println(Thread.currentThread().getName()+ " " +i);if (i == 30) {

Runnable myRunnable= newMyRunnable();

Thread thread= new MyThread(myRunnable);//輸出的是MyThread中的Run方法,多態(tài)的體現

Thread thread1=new Thread(myRunnalbe);//輸出myRunnable中run方法。

thread1.start();

thread.start();

}

}

}

}class MyRunnable implementsRunnable {private int i = 0;

@Overridepublic voidrun() {

System.out.println("in MyRunnable run");for (i = 0; i < 100; i++) {

System.out.println(Thread.currentThread().getName()+ " " +i);

}

}

}class MyThread extendsThread {private int i = 0;publicMyThread(Runnable runnable){super(runnable);

}

@Overridepublic voidrun() {

System.out.println("in MyThread run");for (i = 0; i < 100; i++) {

System.out.println(Thread.currentThread().getName()+ " " +i);

}

}

}

3,生產者消費者模型:

public classProducerConsumer {public static voidmain(String[] args) {

SycnStack ss=newSycnStack();

Runnable producer=newProducer(ss);

Runnable consumer=newConsumer(ss);new Thread(producer,"p1").start();/*new Thread(producer,"p2").start();

new Thread(producer,"p3").start();

new Thread(producer,"p4").start();

new Thread(producer,"p5").start();*/

new Thread(consumer,"c1").start();

}

}classWoTo{intid;

WoTo(intid){this.id=id;

}

@OverridepublicString toString() {return "WOTO"+":"+id;

}

}classSycnStack{

WoTo[] wotoArr=new WoTo[6];int index=0;public synchronized voidpush(WoTo woto){while (index==6){//wotoArr.length==6,當stack中滿6個時,生產停止,需要消費者消費并notify生產者繼續(xù)生產

try{

System.out.println("full");//發(fā)生wait后,如果沒有notify喚醒寫在wait的方法不執(zhí)行。

this.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

wotoArr[index]=woto;

index+=1;this.notifyAll();//生產往后通知消費者,主要是喚醒消費者來消費,如果多線程也會喚醒生產者,但喚醒后任然可能會進入wait中

}public synchronizedWoTo pop(){while (index==0){try{

System.out.println("null");this.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

index-=1;this.notifyAll();//消費完后通知生產者,喚醒生產者來生產,注釋掉會進入死鎖狀態(tài)即,消費者等生產者生產,而生產者在wait中。

returnwotoArr[index];

}

}class Producer implementsRunnable{

SycnStack ss=null;

Producer(SycnStack ss){this.ss=ss;

}

@Overridepublic voidrun() {for (int i=0;i<20;i+=1){//一個線程最多生產20個饅頭

WoTo woto=newWoTo(i);

ss.push(woto);try{

Thread.sleep(200);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+":produce:"+woto);

}

}

}class Consumer implementsRunnable{

SycnStack ss=null;

Consumer(SycnStack ss){this.ss=ss;

}

@Overridepublic voidrun() {for(int i=0;i<20;i+=1){//一個消費者最多消費20個

WoTo woto=ss.pop();try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+":consuemer:"+woto);

}

}

}

4,筆試題1:

public class SyncThread1 implementsRunnable {int num=100;/*m1()和m2()都加了同步鎖,執(zhí)行流程顯示調用run方法中的m1(),對num加同步鎖,然后讓出cpu,開始main線程

調用m2方法,不能訪問不能修改num,結束然后,輸出num,然后讓出cpu,繼續(xù)執(zhí)行m1()方法。sleep并不代表結束就能馬上運行,處于就緒狀態(tài)

需搶占*/

synchronized voidm1(){

num=1000;try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("num"+num);

}synchronized voidm2(){try{

Thread.sleep(500);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(num);

num=2000;//System.out.println(num);

}public voidrun(){

m1();

}public static voidmain(String[] args) {

SyncThread1 syncThread1=newSyncThread1();

Thread thread=newThread(syncThread1);

thread.start();//新開的線程,不和main線程共線程

syncThread1.m2();//在main線程中,因為m2()加了同步鎖,即對num加鎖了,m2無法對num修改,即不執(zhí)行,直接執(zhí)行下面這個輸出

System.out.println(syncThread1.num);//main線程要等syncThread1.m2()執(zhí)行完才執(zhí)行

}

}

5,哲學家問題:

/*問題描述:一圓桌前坐著5位哲學家,兩個人中間有一只筷子,桌子中央有面條。哲學家思考問題,

當餓了的時候拿起左右兩只筷子吃飯,必須拿到兩只筷子才能吃飯。上述問題會產生死鎖的情況,

當5個哲學家都拿起自己右手邊的筷子,準備拿左手邊的筷子時產生死鎖現象。

解決辦法:

1、添加一個服務生,只有當經過服務生同意之后才能拿筷子,服務生負責避免死鎖發(fā)生。

2、每個哲學家必須確定自己左右手的筷子都可用的時候,才能同時拿起兩只筷子進餐,吃完之后同時放下兩只筷子。

代碼實現:實現第2種方案*/

public classPhilosopherDemo {public static voidmain(String[] args) {

Fork fork=newFork();//五個philosopher都指向同一個fork,所以此時相當于成員變量被多個線程共享了

Philosopher philosopher=new Philosopher(fork,0);

Philosopher philosopher1=new Philosopher(fork,1);

Philosopher philosopher2=new Philosopher(fork,2);

Philosopher philosopher3=new Philosopher(fork,3);

Philosopher philosopher4=new Philosopher(fork,4);newThread(philosopher).start();newThread(philosopher1).start();newThread(philosopher2).start();newThread(philosopher3).start();newThread(philosopher4).start();

}

}class Philosopher implementsRunnable{

Fork fork=null;intid;

Philosopher(Fork fork,intid){this.fork=fork;this.id=id;

}

@Overridepublic voidrun() {while(true){

think();

fork.getFork(this);

eat();

fork.offFork(this);

}

}public voidthink(){try{

System.out.println(id+"in thinking");

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}public voideat(){try{

System.out.println(id+"in eating");

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}classFork{boolean[] fork={false,false,false,false,false};//模擬五把叉

public synchronized voidgetFork(Philosopher p){while(fork[p.id]||fork[(p.id+1)%5]){

System.out.println("p:"+p.id+"waiting");try{

wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

fork[p.id]=true;

fork[(p.id+1)%5]=true;

System.out.println("p:"+p.id+"getFork");

}public synchronized voidoffFork(Philosopher p){

fork[p.id]=false;

fork[(p.id+1)%5]=false;

System.out.println("p:"+p.id+"offFork");this.notifyAll();

}

}

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的java多线程多态_Java学习之多线程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。