Java多執行緒——實現執行緒的方式以及執行緒的狀態
阿新 • • 發佈:2019-02-11
什麼是執行緒
執行緒是程序中獨立執行的子任務(程序是受作業系統管理的基本執行單元),在沒有同步的情況下,執行緒的執行是隨機亂序的。
在Java程式設計中,有四種方式去實現多執行緒。
一、實現Runnable介面
Runnable介面中只有一個抽象run()方法,這個方法是執行執行緒的入口,而不是啟動執行緒的入口,啟動執行緒用start()方法,實現這個介面的類就具有了多執行緒的功能了。
public class MyThread implements Runnable {
private String name;
public MyThread(String name) {
this .name = name;
}
@Override
public void run() {
System.out.println("inner thread is running!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
實現Runnable介面的類,需要使用Thread類的建構函式例項化一個執行緒,下面使用了帶有執行緒名稱的建構函式,第二個引數是執行緒名稱。
public Thread(Runnable target, String name)
執行測試:
public static void main(String[] args) {
Thread thread = new Thread(new MyThread("mythread"),"mythread");
thread.start();
System.out.println(thread.getName());
System.out.println("main thread is running!" +Thread.currentThread().getName());
}
執行結果:
mythread
inner thread is running!
main thread is running!main
二、繼承Thread類
其實繼承Thread類實現多執行緒,本質上也是實現了Runnable介面,因為Thread類實現了Runnable介面。
public class MyThread extends Thread {
private String some;
public MyThread(String some) {
this.some = some;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" is running!"+"--"+getSome());
}
public String getSome() {
return some;
}
public void setSome(String some) {
this.some = some;
}
}
實現Thread類,在例項化一個執行緒時,只需要例項化該類。
public static void main(String[] args) {
MyThread thread = new MyThread("mythread");
thread.start();
System.out.println(Thread.currentThread().getName()+" thread is running!" );
}
執行結果:
main thread is running!
Thread-0 is running!--mythread
三、繼承TimerTask類
由於TimerTask實現了Runnable介面,因此繼承TimerTask也能夠實現多執行緒。用這種方法,有兩種方式啟動執行緒。
- 使用定時器Timer的排程方法schedule()。
- 使用Thread的建構函式。
private static Timer timer = new Timer();
public static class Mytask extends TimerTask{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" is running!");
}
}
public static void main(String[] args) {
//第一種啟動方法
Mytask mytask = new Mytask();
timer.schedule(mytask, 1000L);
//第二種啟動方法
Thread thread = new Thread(mytask,"mytask");
thread.start();
}
執行結果:
mytask is running!
Timer-0 is running!
四、實現Callable介面
Callable介面中只有一個call()方法,該方法具有返回值,並且可以丟擲異常。和Runnable介面有很大的區別,是一種更加高階的實現。
public class CallableService<T> implements Callable<T> {
private int age;
public CallableService(int age) {
super();
this.age=age;
}
@Override
public T call() throws Exception {
System.out.println(Thread.currentThread().getName()+" is running!");
return (T) ("返回值是:"+age);
}
}
啟動該執行緒,只需要例項化實現Callable介面的類,然後呼叫call()方法。
執行測試:
public static void main(String[] args) throws Exception {
CallableService<String> service = new CallableService<String>(100);
String t = service.call();
}
測試結果:
返回值是:100
Callable可以結合Future使用,能夠實現更多的功能。這個在後續的部落格中會講到。
執行緒的狀態
- 初始化狀態:即執行緒的新生狀態,使用new出來的執行緒。
- 執行狀態:線上程呼叫start()方法後,且沒有發生任何意外和認為的中斷,此時執行緒處於執行狀態。
- 阻塞狀態:執行緒呼叫wait(),sleep(),suepend()方法後,將處於該狀態。
銷燬狀態:執行緒自然的執行結束或呼叫stop()方法銷燬執行緒。
這個圖不是最完善的,在暫停狀態時,當有執行緒呼叫notify()或notifyAll()方法時,阻塞的執行緒會搶佔監視器,先得到監視器的執行緒先執行。