大家好,我是樂字節的小樂,好看好學的Java乾貨又來了!上一篇我們說到了Java多線程的概念以及優缺點,本文將接着說Java多線程的創建,以及多線程的狀態。
一、創建線程
1、創建 Thread 的子類
創建: 繼承 Thread +重寫 run
啓動: 創建子類對象 對象.start()
創建 Thread 子類的一個實例並重寫 run 方法,run 方法會在調用 start()方法之後被執行,示例如下:
public class MyThread extends Thread {
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(20); //模擬延時
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一邊學習多線程");
}
}
public static void main(String[] args) {
//創建子類對象
MyThread myThread = new MyThread();
//啓動線程
myThread.start();
//也可以創建匿名子類
Thread thread = new Thread(){
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(20);//模擬延時
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一邊玩QQ");
}
}
};
thread.start();
for(int i=0;i<10;i++){
try {
Thread.sleep(20); //模擬延時
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一邊玩微信...");
}
}
}
2、實現 Runnable 接口(推薦)
面向接口編程,避免單繼承侷限
創建: 實現 Runnable +重寫 run
啓動:靜態代理 Thread
a)、創建真實角色 實現類對象
b)、創建代理角色 Thread 對象+真實角色的引用
c)、代理角色.start()
此方式是新建一個實現了 java.lang.Runnable 接口的類的實例,實例中的方法可以被
線程調用。
缺點: 根據重寫規則,run 方法不能對外聲明異常,不能有返回值
public class MyRunnable implements Runnable {
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(20); //模擬延時
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一邊學習多線程");
}
}
public static void main(String[] args) {
//使用代理創建線程
Thread thread = new Thread(new MyRunnable());
//啓動線程
thread.start();
//也可以創建一個實現了Runnable接口的匿名類
Runnable myRunnable = new Runnable(){
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(20);//模擬延時
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一邊玩QQ");
}
}
};
Thread t = new Thread(myRunnable);
t.start();
for(int i=0;i<10;i++){
try {
Thread.sleep(20); //模擬延時
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一邊玩微信...");
}
}
}
優點: 能聲明異常,能有返回值 缺點: 編寫複雜麻煩
public class Call {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//創建線程
ExecutorService ser=Executors.newFixedThreadPool(2);
Race tortoise = new Race("老不死",1000);
Race rabbit = new Race("小兔子",500);
//獲取值
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>{
private String name ; //名稱
private long time; //延時時間
private boolean flag =true;
private int step =0; //步
public Race() {
}
public Race(String name) {
super();
this.name = name;
}
public Race(String name,long time) {
super();
this.name = name;
this.time =time;
}
@Override
public Integer call() throws Exception {
while(flag){
Thread.sleep(time); //延時
step++;
}
return step;
}
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;
}
}
二、線程的狀態及信息
1、五種狀態
1)、新生狀態: new
2)、就緒狀態: runnable
3)、運行狀態: running
4)、阻塞狀態: blocked
5)、執行完畢: dead
類似於運動員賽跑,
1)、新生狀態:選出運動員
2)、就緒狀態:走到起跑線,做好跑的動作,槍響後,不是馬上就跑,得有反應時間。
3)、運行狀態:反應完成後,開始跑
4)、阻塞狀態:路邊一個石頭絆倒了,馬上跑起來,嘟囔幾句,踢踢石頭, 不是馬上跑,重新反應進入就 緒。
5)、終止狀態:跑完了,結束了,慢慢的走幾步停下來。
2、阻塞: sleep
模擬網絡延時,每個對象 都有一把排他鎖,不會釋放鎖
class Web12306 implements Runnable {
private int tickets =20; //假設20張票
private boolean flag =true;
@Override
public void run() {
while(flag){
if(tickets>=0){
try {
//模擬延時
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->搶票"+tickets--);
}else{
flag =false;
}
}
}
public static void main(String[] args) {
//真實角色 目標
Runnable target =new Web12306();
//代理角色 Thread +真實角色的引用
Thread proxy1 =new Thread(target,"黃牛A");
Thread proxy2 =new Thread(target,"路人甲");
//代理行爲
proxy1.start(); //啓動線程
proxy2.start(); //線程不安全,數據有問題
}
}
3、終止
不要調用 stop destory 方法 ,太暴力,一盆冷水讓其停止。
a、正常執行完畢,循環 次數已經到達
b、外部干涉
1)、線程中加入標識 -->屬性
2)、線程體中 使用改標識 -->死循環
3)、對外提供改變改標識的方法 setXxx() terminate() a()...
4)、外部根據適當的時機調用該方法
4、當前線程
Thread.currentThread()
5、優先級
只代表概率,不代表絕對先後順序
MIN_PRIORITY : 1
NORM_PRIORITY :5 默認優先級
MAX_PRIORITY :10
getPriority() setPriority()
關於多線程的創建和狀態就介紹到這裏,下次我們再說多線程的同步和線程通信,請關注樂字節,原創文章,轉載請註明出處。