線程,又稱爲輕量級進程,是程序執行過程中的最小的單位。
JAVA中線程實現
1.是通過繼承JAVA.Lang包裏面的Thread類,重寫裏面的run方法
例如:
class MyThread extends Thread{
private String name;
public MyThread(String name) {
this.name = name ;
}
public void run(){
for(int i=0;i<5;i++)
System.out.println(this.name+"----"+i);
}
}
public class Hello{
public static void main(String []args){
MyThread t1 = new MyThread("線程1");
MyThread t2 = new MyThread("線程2");
MyThread t3 = new MyThread("線程3");
t1.start();
t2.start();
t3.start();
}
}
輸出:
線程1----0
線程1----1
線程1----2
線程1----3
線程1----4
線程3----0
線程2----0
線程3----1
線程2----1
線程2----2
線程2----3
線程3----2
線程3----3
線程3----4
線程2----4
通過查看Thread的源碼發現
Thread繼承了Runnable接口。
**
2.通過實現Runnable接口來實現線程(實際運用更多)
Runnable實現線程沒有返回值
**
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Runnable是一個函數式接口,裏面只包含一個run方法,重寫了run方法之後即可使用線程
**
但是線程的開始只能通過Thread.start()方法
**
Thread類裏面有一個構造器
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
即可通過Runnable對象來構造Thread對象,再通過start方法來運行Runnable裏面的run方法。
例如:
public class Hello{
public static void main(String []args){
//由於是函數式接口,可以採用匿名類,還可以採用Lambda表達式
Runnable r = () ->{
for(int i =0;i<5;i++) {
System.out.println(Thread.currentThread()+"-----"+i);
}
};
Runnable s = () ->{
for(int i =0;i<5;i++) {
System.out.println(Thread.currentThread()+"-----"+i);
}
};
new Thread(r).start();
new Thread(s).start();
}
}
輸出
Thread[Thread-0,5,main]-----0
Thread[Thread-0,5,main]-----1
Thread[Thread-1,5,main]-----0
Thread[Thread-0,5,main]-----2
Thread[Thread-0,5,main]-----3
Thread[Thread-0,5,main]-----4
Thread[Thread-1,5,main]-----1
Thread[Thread-1,5,main]-----2
Thread[Thread-1,5,main]-----3
Thread[Thread-1,5,main]-----4
start的源碼
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
調用這個方法會導致此線程開始執行; Java虛擬機調用此線程的運行方法。
結果是兩個線程同時運行:當前線程(從調用返回到start方法)和另一個線程(執行它的運行方法)。
線程的幾種狀態:
線程創建之後調用start方法,然後就進入就緒狀態等待資源分配系統調用
線程運行過程中可能會因爲資源分配的問題,有別的優先級更高的線程要運行,還沒運行完就回到就緒狀態。
線程運行過程中可能因爲遇到某種阻塞事件進入阻塞狀態
等到阻塞事件解除之後又回到就緒狀態等待調用。
線程運行完之後纔會終止
**
3.通過Callable接口實現線程
**
Callable接口實現線程是可以有返回值,通過實現Callable接口實現call方法即可。
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
但是線程執行最終是通過Thread類的start的方法,而Thread類不能通過Callable對象來構造。
但是Callable繼承了FutureTask類,而FutureTask類實現了Runnable接口,即可以通過new Thread(FutureTask)來創建Thread
FutureTask裏面有一個get方法可以獲得call方法的返回值。
class Person<String> implements Callable<String>{
private int number =10;
public String call() throws Exception {
for(int i =0;i<10;i++) {
if(number>0) {
System.out.println(Thread.currentThread()+"-----"+number--);
}
}
return (String) ((String) Thread.currentThread()+"線程執行完畢");
}
}
public class Hello{
public static void main(String []args) throws InterruptedException, ExecutionException{
Person p = new Person();
//如果想獲得返回值,那麼這裏可以
//FutureTask t = new FutureTask(p);
//t.get();
new Thread(new FutureTask(p)).start();
new Thread(new FutureTask(p)).start();
}
}
輸出:
Thread[Thread-0,5,main]-----10
Thread[Thread-0,5,main]-----8
Thread[Thread-0,5,main]-----7
Thread[Thread-1,5,main]-----9
Thread[Thread-0,5,main]-----6
Thread[Thread-1,5,main]-----5
Thread[Thread-0,5,main]-----4
Thread[Thread-0,5,main]-----2
Thread[Thread-0,5,main]-----1
Thread[Thread-1,5,main]-----3