done like this:
Thread thread = new Thread();
thread.start();
複製程式碼
線上程中執行程式碼的兩種方式
Thread子類
public MyThread extends Thread{
@Override
public void run() {
System.out.println("Hello, World!");
}
}
複製程式碼
Runable實現類
public MyRunnable implements Runnable{
public void run() {
System.out.println("all so have to say hello, world!");
}
}
複製程式碼
匿名內部類
Runnable myRunnable = new Runnable() {
public void run() {
System.out.println("Hello, World!");
}
};
複製程式碼
Lambda
Runnable myRunable = {
System.out.println("Hello, World!");
};
複製程式碼
兩種方式對比
通過實現介面的方式,能夠讓程式碼書寫更加精簡。可以通過Lambda來簡化程式碼。實現介面的方式能夠有效分離業務邏輯與執行緒執行程式碼,能讓執行緒池有效管理和排程任務,線上程池繁忙時進入佇列等待執行緒池排程。這種方式能夠迎合工作者模型。
有時候可以結合兩種方式來使用,最典型的代表就是實現一個執行緒池。
常見錯誤:用run()方法來代替start()執行
Thread newThread = new Thread(MyRunnable());
newThread.run(); //should be start();
複製程式碼
僅執行run方法,並不會建立新的執行緒,而是在本執行緒來執行run方法裡面的業務邏輯。切記建立一個新的執行緒,一定要執行start方法而非run方法。
執行緒名稱
往往為了區分哪個執行緒在執行,會通過System.out的方式來列印執行緒名稱。通過繼承Thread的方式可以直接通過Thread的getName方法來列印名稱。通過實現的方式並沒有getName方法,此時可以通過Thread的靜態方法currentThread來取得當前執行緒引用。
在建立執行緒時,可以通過Thread的構造方法傳遞執行緒名稱;
Thread myThread = new Thread("our-thread0") {
@Override
public void run() {
System.out.println("run by: " + getName());
}
};
Runnable myRunnable = () -> {
final Thread currentThread = Thread.currentThread();
System.out.println("run by: " + currentThread.getName());
};
myThread.start();
new Thread(myRunnable, "our-thread1").start();
複製程式碼
Java執行緒例項
public class ThreadExample {
private static void startThread(int i) {
new Thread("thread: " + i) {
@Override
public void run() {
System.out.println(getName() + " running.");
}
}.start();
}
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
IntStream.range(0, 10)
.forEach(ThreadExample::startThread);
}
}
複製程式碼
如你所見,以上例項中,順序建立並執行10個執行緒,但執行緒的執行並不一定是順序,此時10個執行緒是並行執行的,執行緒的執行順序是由jvm和作業系統共同決定的。
暫停執行緒
try {
// 當前執行緒睡眠 10 s
Thread.sleep(10L * 1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
複製程式碼
可以通過Thread.sleep()方法,通過傳遞毫秒數來暫停執行緒。暫停時長以傳遞毫秒數為準。
停止執行緒
Thread物件中預設包含了stop(),pause()等方法。但已經被廢棄了,預設的stop()方法並不能保證執行緒在何種狀態下被停止。這意味著,所有被執行緒訪問到的java物件都將在一個未知的狀態下執行。如果其他執行緒需要訪問相同的物件,那麼你的應用將會出現不可預測的失敗。
public class ThreadStopExample implements Runnable {
// 是否停止
private boolean doStop = false;
// 繼續執行執行緒
public synchronized boolean keepRunning() {
return !doStop;
}
// 停止執行緒
public synchronized void stop() {
this.doStop = true;
}
@Override
public void run() {
while (keepRunning()) {
System.out.println("Running");
try {
// 暫停 3 s
Thread.sleep(3L * 1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final ThreadStopExample threadStopExample = new ThreadStopExample();
new Thread(threadStopExample, "our thread").start();
try {
// 10 s 後停止執行緒
Thread.sleep(10L * 1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadStopExample.stop();
}
}
複製程式碼