多執行緒_callable_執行緒的狀態_執行緒的停止_執行緒的阻塞(join,yield,sleep)_currentThread_priority_day30
阿新 • • 發佈:2019-01-23
1.使用callable介面實現多執行緒
我們繼續用這個多執行緒來實現龜兔賽跑:
package callable; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * 我們用callable來模擬一下龜兔賽跑 * * @author Wang * */ public class Demo { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService ser = Executors.newFixedThreadPool(2);//這裡就是建立兩個執行緒 Race tortoise = new Race("烏龜",1000);//1s走一步 Race rabbit = new Race("小兔子",500);//0.5s Future<Integer> result1 =ser.submit(tortoise) ;//獲取執行緒體返回過來的值 要用對應的型別進行接收 Future<Integer> result2 =ser.submit(rabbit) ; Thread.sleep(2000); //2秒 讓執行緒執行兩秒 tortoise.setFlag(false); //停止執行緒體迴圈 rabbit.setFlag(false); int num1 =result1.get(); //注意這個地方要接收值 int num2 =result2.get(); System.out.println("烏龜跑了-->"+num1+"步"); System.out.println("小兔子跑了-->"+num2+"步"); //停止服務 ser.shutdownNow();//關閉執行緒 } } class Race implements Callable <Integer> {//這裡的Integer的作用是返回的是Interger型別的 private String name; //建立的這個執行緒叫什麼名字 private long time; //多長時間走一步 private boolean flag = true;//標誌位 private int step;//走了多少步 public Race() { } public Race(String name, long time) { super(); this.name = name; this.time = time; } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getTime() { return time; } public void setTime(long time) { this.time = time; } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public int getStep() { return step; } public void setStep(int step) { this.step = step; } @Override public Integer call() throws Exception { while(flag) { Thread.sleep(time);//程式睡眠多長時間 就是相當於多長時間走了一步 step++; } return step; } }
2.執行緒的狀態:
2.執行緒的停止:
注意:其實Thread類(代理)裡面也有執行緒停止的方法只不過這些方法,不推薦使用,主要是這些方法不安全;package Stop; /** * * 外部干涉來停止執行緒 * * @author Wang * */ public class StopDemo01 { public static void main(String[] args) throws InterruptedException { run r = new run();//搞清楚誰是實體 new Thread(r).start();//這裡使用的是匿名類 for(int i=0;i<30;i++) { if(i==10) { //外部根據條件來呼叫停止對方法; r.stop(); } System.out.println(i); } } } class run implements Runnable{ private boolean flag = true;//定義執行緒體中使用的標識 @Override public void run() { while(flag) {//執行緒體使用該標識 System.out.println("執行緒ing....."); } } void stop() {//提供外部的方法來改變標識 flag = false; yi } }
3.執行緒的阻塞:
1.join():合併執行緒
package Stop; /** * * 執行緒的阻塞 Join * * @author Wang * */ public class JoinDemo01 extends Thread { public static void main(String[] args) throws InterruptedException { JoinDemo01 j = new JoinDemo01();//新生 Thread t = new Thread(j); t.start();//就緒 //cpu執行排程 for(int i=0;i<200;i++) { if(i==50) { t.join();//這裡會把兩個執行緒合為一個 會繼續執行t但是變為了單執行緒 他執行玩以後在執行main()函式 所以我們就說main函式被阻塞; } System.out.println("main執行" + i); } } public void run() {// 重寫run()方法 這個就是執行緒體 for (int i = 0; i < 200; i++) { System.out.println("執行j" + i); } } }
2.yield():暫停自己的執行緒 static
package Stop;
/**
*
* 測試Yield
*
* @author Wang
*
*/
public class Yield extends Thread{
public static void main(String[] args) {
Yield y = new Yield();
Thread t = new Thread(y);
t.start();
for(int i=0;i<50;i++) {
if(i==10) {
Thread.yield();//他是一個靜態方法 在哪個執行緒裡呼叫就會暫停那個執行緒 這個暫停只是暫停一瞬間
}
System.out.println("main" + i);
}
}
public void run() {// 重寫run()方法 這個就是執行緒體
for (int i = 0; i < 100; i++) {
System.out.println("執行y" + i);
}
}
}
3.sleep();睡眠 static,不釋放鎖(常用的方法)one:與時間相關(模擬倒計時)
two:模擬網路延時
package Stop;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
* 測試一下sleep的用法
*
* @author Wang
*
*/
public class sleep {
public static void main(String[] args) throws InterruptedException {//寫一個當前時間的倒計時
Date endTime = new Date(System.currentTimeMillis()+10*1000);//得到倒計時的開始時間 當前時間10s後的時間
long end = endTime.getTime();
while(true) {
System.out.println(new SimpleDateFormat("mm:ss").format(endTime));//將這個時間格式化為字串型別 採用了匿名類 這裡給你所在的地區時間不太一致是牽涉到時區的問題
Thread.sleep(1000);
endTime = new Date(endTime.getTime() - 1000);
if(end-10000 >= endTime.getTime()) {//倒計時10後跳出
break;
}
}
}
}
看一下網路延時給我們帶來的問題:
package Stop;
import Runnable.Web;
/**
*
* 來看一下網路延時所帶來的問題
*
* @author Wang
*
*/
public class SleepDemo02 implements Runnable{
private int ticketNum = 50;
@Override
public void run() {
while(true) {
if(ticketNum<0) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "搶到了" + ticketNum--);
}
}
public static void main(String[] args) {
SleepDemo02 web = new SleepDemo02();//建立實體物件
Thread thr1 = new Thread(web,"路人甲");//建立四個代理 他們來實現多執行緒的搶票
Thread thr2 = new Thread(web,"黃牛");
Thread thr3 = new Thread(web,"程式設計師");
Thread thr4 = new Thread(web,"白領");
thr1.start();
thr2.start();
thr3.start();
thr4.start();
}
}
從這張圖上我們可以看到搶票搶到-1的情況
看這裡當最後一次搶票的時候,這時候票還剩兩張,我們第一個代理和第二個代理都會進去while() 但是他們會休眠所以num還是大於0的 不跳出迴圈 這樣我們的另外兩個代理都會進入程式中,就會拿到0和-1;
4.測試currentThread()
package priority;
/**
*
* 自己寫一個執行緒的實體
*
* @author Wang
*
*/
public class MyThread implements Runnable{
private int num = 0;
private boolean flag = true;
@Override
public void run() {
while(flag) {
System.out.println(Thread.currentThread().getName() + num++);//得到當前執行緒的名字;
}
}
public void stop() {
flag = false;
}
}
package priority;
/**
*
* 我們來測試一下這個類
*
* @author Wang
*
* Thread.currentThread() :當前執行緒
* setName():設定名稱
* getName():獲取名稱
* isAlive():判斷狀態
*
*/
public class currentThread {
public static void main(String[] args) throws InterruptedException {
MyThread mt = new MyThread();//建立一個是實體
Thread proxy = new Thread(mt,"wang");
proxy.setName("wanga");//更改執行緒的名字
System.out.println(proxy.getName());
System.out.println(Thread.currentThread().getName());//獲取當前執行緒的名字 在這裡應該是Main
proxy.start();
System.out.println(proxy.isAlive());
Thread.sleep(5);
mt.stop();
Thread.sleep(5);// 這裡需要延時一下 給執行緒一個關閉的時間;
System.out.println(proxy.isAlive());
}
}
5.測試priority()
package priority;
/**
*
* 我們來了解一下執行緒優先順序的問題
* 優先順序:概率,不是絕對的先後順序
* MAX_PRIORITY 10
* NORM_PRIORITY 5 (預設的優先順序是這個)
* MIN_PRIORITY 1
*
* setPriority()
* getPriority()
*
* @author Wang
*
*/
public class PriorityDemo01 {
public static void main(String[] args) throws InterruptedException {
MyThread mt =new MyThread();
Thread p1 =new Thread(mt,"aione");
MyThread mt2 =new MyThread();
Thread p2 =new Thread(mt2,"aitwo");
p1.setPriority(Thread.MIN_PRIORITY); //設定優先順序
p2.setPriority(Thread.MAX_PRIORITY);//設定優先順序 他的優先順序高 那麼他執行的概率就比較大
p1.start();
p2.start();
Thread.sleep(1);
mt.stop();
mt2.stop();
}
}
注意:我們學習java的基本知識就是學類和介面的;
執行緒的優先順序高 就是執行他的概率大一點 而不是先執行優先順序高的 在執行優先順序低的;