您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“Java多線程怎么設(shè)置優(yōu)先級(jí)”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
舉例說明:
我們知道飛機(jī)在天上飛行是有固定的航線(可以理解成線程),每個(gè)機(jī)場(chǎng)都有最大的運(yùn)行負(fù)載能力,當(dāng)運(yùn)行情況超過了負(fù)載能力的時(shí)候,這就需要塔臺(tái)調(diào)度參與,會(huì)根據(jù)每架飛機(jī)的優(yōu)先級(jí)排序。當(dāng)在航線的時(shí)候,如果出現(xiàn)緊急情況,會(huì)讓其他飛機(jī)避讓,讓這架飛機(jī)優(yōu)先級(jí)提高,先降落。這就是調(diào)度,計(jì)算機(jī)程序線程運(yùn)行也是這樣的。
在Java多線程中,主要可以通過下面四個(gè)方法來分配CPU的使用權(quán):
設(shè)置優(yōu)先級(jí)(Priority) 設(shè)置線程的優(yōu)先級(jí),值是1-10
休眠(sleep) 單位毫秒,讓本線程屬于阻塞狀態(tài),CPU會(huì)執(zhí)行其他線程
強(qiáng)制運(yùn)行(join) 讓這個(gè)線程強(qiáng)制獲取CPU資源來運(yùn)行
禮讓(yield) 暫停正在執(zhí)行的線程,讓其他線程先執(zhí)行,執(zhí)行完了在接著執(zhí)行
有兩個(gè)線程,分別設(shè)置最大優(yōu)先級(jí)和最小優(yōu)先級(jí):
public class MyThread implements Runnable{ @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+"正在運(yùn)行:"+i); } } public static void main(String[] args) { Thread t1 = new Thread(new MyThread(),"線程A:"); Thread t2 = new Thread(new MyThread(),"線程B***:"); //設(shè)置優(yōu)先級(jí): 最高為10 最低為1 t1.setPriority(Thread.MAX_PRIORITY); t2.setPriority(Thread.MIN_PRIORITY); //顯示線程優(yōu)先級(jí): System.out.println("線程A的優(yōu)先級(jí)是:"+t1.getPriority()); System.out.println("線程B的優(yōu)先級(jí)是:"+t2.getPriority()); t1.start(); t2.start(); } }
結(jié)果:
Thread.sleep();--------單位是毫秒,讓本線程屬于阻塞狀態(tài),CPU會(huì)執(zhí)行其他線程:
public class ThreadSleep { public static void main(String[] args) { sleepTime(5); } private static void sleepTime(int time) { for (int i = 0; i < 5; i++) { System.out.println("主線程執(zhí)行了:"+i+"s"); try{ //讓線程休眠,進(jìn)入阻塞狀態(tài) Thread.sleep(1000); //休眠時(shí)間為1000毫秒 } catch (InterruptedException e) { e.printStackTrace(); } } } }
結(jié)果:
顧名思義,就是讓某個(gè)線程強(qiáng)制進(jìn)入執(zhí)行:
子線程:
public class MyThread { }
測(cè)試類:
public class Test { public static void main(String[] args) throws InterruptedException { Thread t1= new Thread(new MyThread(),"我是子線程"); t1.start(); //當(dāng)主線程執(zhí)行任務(wù)1-10時(shí),如果執(zhí)行到5就讓子線程t1強(qiáng)制進(jìn)來執(zhí)行,直到執(zhí)行完了才讓主線程繼續(xù)執(zhí)行任務(wù) for (int i = 0; i < 6; i++) { if (i==2){ t1.join(); } System.out.println(Thread.currentThread().getName()+"正在運(yùn)行:"+i); } } }
結(jié)果:
暫停正在執(zhí)行的線程,讓其他線程先執(zhí)行,執(zhí)行完了在接著執(zhí)行:
public class MyThread implements Runnable{ //線程禮讓,讓本線線程阻塞,其他線程先執(zhí)行 //這里就是A線程運(yùn)行二次后,禮讓,讓B 線程先執(zhí)行 //也是理論上的,就是不管怎么樣第二次后面肯定讓B先執(zhí)行,但是后面就隨機(jī)了 @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+"正在運(yùn)行:"+i); if(i == 2){ Thread.yield(); } } } }
測(cè)試類:
public class Test { public static void main(String[] args) { Thread t1 = new Thread(new MyThread(),"線程A:"); Thread t2 = new Thread(new MyThread(),"----線程B"); t1.start(); t2.start(); } }
結(jié)果:
定時(shí)器就是可以設(shè)置某個(gè)時(shí)間點(diǎn)來執(zhí)行某個(gè)事件,比如系統(tǒng)每周刪除依次日志文件,或者在指定的日期關(guān)閉系統(tǒng),定時(shí)器本身就是一個(gè)線程任務(wù)來在指定的時(shí)候執(zhí)行該任務(wù)。定時(shí)器是繼承TimerTask來重寫run方法,專門處理定時(shí)任務(wù)。
演示Demo:
public class MyThread extends TimerTask { @Override public void run() { //把任務(wù)定義在run方法中 showMyself(); } public void showMyself(){ System.out.println("被Run方法執(zhí)行的"); } }
測(cè)試類:
public class Test { public static void main(String[] args) { Timer timer = new Timer(); //設(shè)置5秒后執(zhí)行這個(gè)任務(wù),并且每1秒重復(fù)執(zhí)行這個(gè)任務(wù) timer.schedule(new MyThread(),5000,1000); } }
結(jié)果:
首先我們先看一個(gè)demo:
創(chuàng)建了兩個(gè)線程對(duì)象,一個(gè)線程A任務(wù)用于執(zhí)行print1,另一個(gè)線程B任務(wù)用于執(zhí)行print2:
public void print1(){ System.out.print("中"); System.out.println("國"); } public void print2(){ System.out.print("浙"); System.out.println("江"); } }
測(cè)試類:
public class Test { public static void main(String[] args) { Printer p = new Printer(); //A: new Thread(new Runnable() { @Override public void run() { while(true){ p.print1(); } } },"線程A:").start(); //B: new Thread("線程B:"){ @Override public void run(){ while (true){ p.print2(); } } }.start(); } }
這個(gè)程序就是當(dāng)線程A執(zhí)行的時(shí)候,輸出中國,當(dāng)B執(zhí)行的時(shí)候,輸出浙江,理論上是沒有任何問題,但是我們看一下結(jié)果:
我們發(fā)現(xiàn)出問題了,其實(shí)這就是非線程同步(異步):
同步:提交請(qǐng)求->等待服務(wù)器處理->處理完返回 這個(gè)期間客戶端瀏覽器不能干任何事
異步:請(qǐng)求通過事件觸發(fā)->服務(wù)器處理(這是瀏覽器仍然可以作其他事情)->處理完畢
其實(shí)非線程同步在有些系統(tǒng)是很危險(xiǎn)的問題,比如12306,如果使用非線程同步,那么后果可想而知,那么該如何同步呢? 這里介紹一個(gè)常用的方法,就是上鎖:
如果兩端代碼(兩個(gè)線程任務(wù))是同步的,那么CPU同一時(shí)間只能執(zhí)行一個(gè)任務(wù),相當(dāng)于給該線程上了一把鎖, 在該線程沒有執(zhí)行完這段代碼或者任務(wù)的時(shí)候,其他線程是不能占用CPU資源執(zhí)行任務(wù)的。直到執(zhí)行完了該線 程的代碼,其他線程才可以執(zhí)行。
更好的理解(舉例):
你去公共廁所上廁所(大的),當(dāng)你進(jìn)去后,需要把門關(guān)上并鎖著,這就是上鎖,為了保證你正常的結(jié)束(保證線程正常運(yùn)行完),這期間其他人是不能進(jìn)來的。
Synchronized 鎖:
兩個(gè)線程任務(wù)使用同一個(gè)對(duì)象為鎖,那么兩個(gè)線程方法是同步的 我們把上面的方法上個(gè)鎖:
class Demo { } public class Printer { //創(chuàng)建任意一個(gè)對(duì)象,只要是對(duì)象相同就是鎖相同,就是同步的! Demo d = new Demo(); public void print1(){ //當(dāng)進(jìn)入print1這個(gè)方法時(shí),synchronized就給這個(gè)方法上了一個(gè)鎖 synchronized (d){ System.out.print("中"); System.out.println("國"); } } public void print2(){ //當(dāng)進(jìn)入print2這個(gè)方法時(shí),synchronized也給這個(gè)方法上了一個(gè)鎖 synchronized (d){ System.out.print("浙"); System.out.println("江"); } } }
這樣輸出后就不會(huì)出現(xiàn)上面的那個(gè)問題,這里就不發(fā)結(jié)果截圖啦。大家可以自己試一試,看看是否解決了這個(gè)問題~
我們還可以把鎖直接定義在方法上,比如這樣子:
public static synchronized void print1(){ System.out.print("中"); System.out.println("國"); }
如果是靜態(tài)方法,上鎖的方式是通過.class字節(jié)碼對(duì)象:
public static void print1() { synchronized (Printer.class) { System.out.print("中"); System.out.println("國"); } }
“Java多線程怎么設(shè)置優(yōu)先級(jí)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。