1.1方式一:繼承Thread類
1.自定義類繼承Thread類 2.自定義類重寫run()方法3.創建自定義類對象 4.調用start()方法
class MyThread extends Thread {
private String title;
@Override
public void run() {
for(int x=0;x<15;x++)
System.out.println(this.title+"運行,"+x);
}
public MyThread(String title) {
this.title = title;
}
}
public class ThreadDemo {
public static void main(String[] args) {
new MyThread("線程A").start();
new MyThread("線程B").start();
}
}
1.2方式二:實現Runnable接口
1.自定義類實現Runnable接口 2.自定義類重寫run()方法3.創建自定義類對象
4.創建Thread對象,並把自定義類對象作爲構造參數5.調用start()方法
class MyThread implements Runnable {
private String title;
@Override
public void run() {
for(int x=0;x<5;x++)
System.out.println(this.title+"運行,"+x);
}
public MyThread(String title) {
this.title = title;
}
}
public class ThreadDemo {
public static void main(String[] args) {
//普通格式
Thread threadA = new Thread(new MyThread("線程A"));
Thread threadB = new Thread(new MyThread("線程B"));
Thread threadC = new Thread(new MyThread("線程C"));
threadA.start();
threadB.start();
threadC.start();
//lambda表達式格式
for(int x=0;x<3;x++){
String title = "線程"+x;
new Thread(()->{
for(int y=0;y<5;y++){
System.out.println(title+"運行,y="+y);
}
}).start();
}
}
}
1.3 方式三:實現Callable接口
1.自定義類實現callable接口 2.自定義類重寫call()方法 3.創建自定義類對象
4.創建FutrueTask對象,將自定義類對象作爲參數傳遞到FutrueTask構造器中
5.,創建Thread對象,把FutureTask對象作爲參數傳遞Thread構造器中,調用start()方法
6.調用FutureTask對象get()方法,獲取Callable中call方法中的返回值
class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
for(int i = 0;i<10;i++){
System.out.println("********i"+i);
}
return "線程執行完畢";
}
}
public class ThreadDemo {
public static void main(String[] args) {
try {
FutureTask<String> stringFutureTask = new FutureTask<String>(new MyThread());
new Thread(stringFutureTask).start();
System.out.println("線程返回數據"+stringFutureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
總結:
1、 調用發現,雖然調用start()方法,但是最終執行的是run()方法。正常情況下,如果要想使用一個類中的方法,那麼肯定要產生實例化對象,而後去調用類中提供的方法,但是run()方法不能直接調用的,因爲這牽扯到一個操作系統的資源調度問題,所以要想啓動多線程必須使用start()方法。 源碼內start()→start0() (java native interface-本地操作系統支持方法)
2、任何情況下,只要定義了多線程,多線程的啓動永遠只有一種方案:Thread類中的start方法
3、多線程開發的本質上是多個線程可以進行同一資源的搶佔,Thread主要描述的是線程,而資源的描述是通過Runnable完成的
4、線程運行狀態:start()後爲準備就緒狀態,等待資源調度,當線程調度之後進入運行狀態(即run()),但是線程運行時不會保證一直運行下去,中間可能會產生一些暫停進入阻塞暫停,隨後又進入就緒狀態,直到運行終止.如下圖所示