java 多執行緒Thread類
Thread類之前在部落格簡單介紹了下,本篇重點介紹幾個常用方法:
先看構造方法:
Thread() 建立新的執行緒物件
Thread(String name) 基於指定的名字建立一個執行緒物件
Thread(Runnable target)基於Runnable介面實現類的例項(可以是匿名內部類)建立一個執行緒物件
Thread(Runnable t,String name) 根據給定的Runnable介面實現類的例項和指定的名字建立一個執行緒物件
常用屬性和方法:
private int priority;執行緒優先順序
private boolean daemon = false;是否是保護執行緒
public static final int MIN_PRIORITY = 1;最小優先順序
public static final int NORM_PRIORITY = 5;中等優先順序
public static final int MAX_PRIORITY = 10;最大優先順序
synchronized void start() 啟動執行緒
void run() 如果建立執行緒時使用的是繼承Tread類建立的,要重寫run方法,執行緒體放在run方法裡
final synchronized void setName(String name) 設定執行緒名字
final String getName() 獲取執行緒名字,不能在Runnable介面的實現類或者匿名內部類中重寫的run方法中呼叫
static native void yield(); 禮讓,暫停當前執行緒,多個執行緒(包括當前執行緒)再次搶佔cpu使用權
static native void sleep(long millis) throws InterruptedException;該方法可以使當前執行緒睡眠,執行緒睡眠後,裡面的任務不會執行,待睡眠時間過後會自動甦醒,從而繼續執行任務。引數為毫秒,在run方法中不能丟擲該異常,只能捕獲該異常,因為Thread類中run方法不能丟擲異常,重寫的方法不能比父類異常型別大
static void sleep(long millis, int nanos)throws InterruptedException,第一個引數毫秒,第二個引數納秒,可以設定更精確的睡眠時間
void interrupt()//喚醒睡眠的執行緒,會丟擲InterruptedException異常(好像人睡覺,誰都不希望突然被叫醒)
final void setPriority(int newPriority)//設定執行緒的優點級,從1到10這10中優先順序,10的優先順序最高,優先順序高的並不是就先執行完,而是cpu會分給它較多的時間去執行
final int getPriority()//獲取優先順序等級
final void join() throws InterruptedException//讓執行緒A加入,加入後要一次性執行完這個加入的執行緒A,再接著執行剛才沒執行完的執行緒,繼承Thread類的自定義類中重寫的run方法中只能捕獲該異常,而不能丟擲
final void setDaemon(boolean on),設定守護執行緒,當其他非守護執行緒都執行完成時,守護執行緒自動退出,比如java虛擬機器的垃圾回收器就是守護執行緒
final boolean isDaemon()//判斷是否為守護執行緒
以下的演示如果設計到兩個類就寫一個繼承Thread的類寫一個匿名內部類
sleep()休眠
public class ThreadSleepTest01 { public static void main(String[] args){ Thread t1=new Thread("t1"){ @Override public void run() { for (int i=0;i<10;i++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println( "Thread "+this.getName()+"will sleep"); } } }; SleepThread st=new SleepThread("sleepThread"); t1.start(); st.start(); } } class SleepThread extends Thread{ public SleepThread(String name){ super(name); } @Override public void run() { for (int i=0;i<10;i++){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println( this.getName()+" is Sleeping"); } } } out: Thread t1will sleep Thread t1will sleep Thread t1will sleep Thread t1will sleep Thread t1will sleep sleepThread is Sleeping sleepThread is Sleeping sleepThread is Sleeping sleepThread is Sleeping sleepThread is Sleeping
結果說明,在SleeoThread執行緒還在休眠時,Threadt1執行緒已經執行完畢
interrupt()喚醒,將正在休眠的執行緒喚醒,會丟擲異常
public class ThreadInterruptTest01 { public static void main(String[] args){ SleepInterrupt si =new SleepInterrupt("睡眠喚醒執行緒"); si.start(); si.interrupt(); } } class SleepInterrupt extends Thread{ public SleepInterrupt(String name){ super(name); } @Override public void run() { try { Thread.sleep(100000); } catch (InterruptedException e) { e.printStackTrace(); } for (int i=0;i<10;i++){ System.out.println(this.getName()+i ); } } } out: java.lang.InterruptedException: sleep interrupted at java.base/java.lang.Thread.sleep(Native Method) at ThreadMethodTest.SleepInterrupt.run(ThreadInterruptTest01.java:18) 睡眠喚醒執行緒0 睡眠喚醒執行緒1 睡眠喚醒執行緒2 睡眠喚醒執行緒3 睡眠喚醒執行緒4 睡眠喚醒執行緒5 睡眠喚醒執行緒6 睡眠喚醒執行緒7 睡眠喚醒執行緒8 睡眠喚醒執行緒9
setPriority()方法設定執行緒的優先順序,Thread提供了三個靜態int變數,從1到10的共10個等級,執行緒優先順序高的cpu分配給其較多的執行時間
優先順序最低:public final static int MIN_PRIORITY = 1;
優先順序居中:public final static int NORM_PRIORITY = 5;
優先順序最高:public final static int MAX_PRIORITY = 10;
示例:
package ThreadMethodTest;
public class ThreadPriorityTest01 {
public static void main(String[] args){
Thread t=new Thread("執行緒t"){
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println( this.getName()+" : "+i);
}
}
};
MyThread3 mt3=new MyThread3("執行緒mt3");
t.setPriority(2);
mt3.setPriority(10);
t.start();
mt3.start();
}
}
class MyThread3 extends Thread{
public MyThread3(String name){
super(name);
}
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println( this.getName()+" : "+i);
}
}
}
yield()禮讓,該方法執行時,只是暫停了此執行緒,但不會保證多個執行緒(包括當前執行緒)誰能拿到cpu控制權,優先讓其他執行緒執行,
public class ThreadYieldTest01 {
public static void main(String[] args){
Thread t1=new Thread("執行緒t1"){
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println( this.getName()+" : "+i);
}
}
};
MyThread4 mt4=new MyThread4("執行緒mt4");
t1.start();
mt4.start();
}
}
class MyThread4 extends Thread{
public MyThread4(String name){
super(name);
}
@Override
public void run() {
for (int i=0;i<100;i++){
if (i%2==0){
Thread.yield();//禮讓,讓寫的執行緒執行
}
System.out.println(this.getName()+" : "+i );
}
}
}
out:
結果太長,不貼出來了,但執行緒t1先執行完
join()加入執行緒,當A執行緒正在執行中加入B執行緒時,cpu先去執行B執行緒,B執行緒執行完再來執行A執行緒,加入之前時cpu排程執行執行緒
示例:
public class ThreadJoinTest01 {
public static void main(String[] args){
Thread t=new Thread("執行緒t"){
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println(this.getName()+" : "+i );
}
}
};
MyThread5 mt5=new MyThread5("執行緒mt5",t);
t.start();
mt5.start();
}
}
class MyThread5 extends Thread{
Thread t1;
public MyThread5(String name,Thread t1){
super(name);
this.t1=t1;
}
@Override
public void run() {
for (int i=0;i<100;i++){
if (i==10){
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println( this.getName()+" : "+i);
}
}
}
out:
結果太長,就不貼出來了
執行緒mt5執行到i=10時,不再執行,開始執行執行緒t,等執行緒t執行完成後,再繼續執行mt5
使用兩個匿名內部類來演示join方法:
package ThreadMethodTest;
public class ThreadJoinTest02 {
public static void main(String[] args){
Thread t1=new Thread("執行緒t1"){
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println( this.getName()+" : "+i);
}
}
};
Thread t2=new Thread("執行緒t2"){
@Override
public void run() {
for (int i=0;i<100;i++){
if (i==10){
try {
// t1.start(); //如果t1.start放在這裡,t2會先列印到9,然後t1開始執行,t1執行完後再執行t2
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.getName()+" : "+i);
}
}
};
t1.start();//剛開始執行時兩個執行緒搶佔cpu,但當t2的i到10時,開始執行t1執行緒,執行完t1後才繼續執行t2
t2.start();
}
}
setDaemon(boolean on),設定守護執行緒
package ThreadMethodTest;
public class ThreadDeamonTest01 {
public static void main(String[] args){
MyThread6 mt6=new MyThread6("執行緒mt6");
Thread t=new Thread("執行緒t"){
@Override
public void run() {
for (int i=0;i<100;i++) {
System.out.println(this.getName() + "是" + (this.isDaemon() ? "守護執行緒" : "非守護執行緒"));
}
}
};
t.setDaemon(true);
t.start();
mt6.start();
}
}
class MyThread6 extends Thread{
public MyThread6(String name){
super(name);
}
@Override
public void run() {
for (int i=0;i<10;i++){
System.out.println( this.getName()+"是"+(this.isDaemon()?"守護執行緒":"非守護執行緒"));
}
}
}
out:
執行緒mt6是非守護執行緒
執行緒t是守護執行緒
執行緒mt6是非守護執行緒
執行緒t是守護執行緒
執行緒mt6是非守護執行緒
執行緒t是守護執行緒
執行緒mt6是非守護執行緒
執行緒t是守護執行緒
執行緒mt6是非守護執行緒
執行緒t是守護執行緒
執行緒mt6是非守護執行緒
執行緒t是守護執行緒
執行緒mt6是非守護執行緒
執行緒t是守護執行緒
執行緒mt6是非守護執行緒
執行緒t是守護執行緒
執行緒mt6是非守護執行緒
執行緒t是守護執行緒
執行緒mt6是非守護執行緒
執行緒t是守護執行緒
執行緒t是守護執行緒
執行緒t是守護執行緒
執行緒t是守護執行緒
執行緒t是守護執行緒
執行緒t是守護執行緒
執行緒t是守護執行緒
執行緒t是守護執行緒
執行緒t是守護執行緒
執行緒t是守護執行緒
可以看到當非守護執行緒結束後,守護執行緒執行了一段時間,還沒執行完就不再執行了